Compare commits
46 Commits
eekboard-0
...
eekboard-0
| Author | SHA1 | Date | |
|---|---|---|---|
| 76d1b8f7fb | |||
| 2bbc65958a | |||
| cbdd0fd2ba | |||
| 2f7aa77c11 | |||
| bed39570ff | |||
| 8bc3b204b4 | |||
| fa030ebcbb | |||
| af365024b7 | |||
| c742877b77 | |||
| ace4391b79 | |||
| 627cbf2898 | |||
| baae80fa41 | |||
| 9be07710dd | |||
| 163e005561 | |||
| d8e691d3f5 | |||
| 85a1a6ba24 | |||
| 828a59b298 | |||
| f1b91c0223 | |||
| cadb0f18a9 | |||
| 2a8d7cf0a8 | |||
| c9b54ba87f | |||
| d57ae91995 | |||
| dd86b132ce | |||
| 3967558bae | |||
| 668ce51f3c | |||
| 1db2a4aeea | |||
| e20425f385 | |||
| a20224f969 | |||
| d66318a031 | |||
| 37c2579253 | |||
| 23ab2a343f | |||
| e6dfc595ab | |||
| 98e15d7741 | |||
| 38b226b46f | |||
| c53b4d398e | |||
| fbcf6b6c65 | |||
| 09c95b20da | |||
| a7f81c3cfb | |||
| a66256f390 | |||
| 8b7da18641 | |||
| a9c0356611 | |||
| b25a9a5407 | |||
| 8b632356e9 | |||
| b8a01d794e | |||
| cfd33921a1 | |||
| 979aa010b9 |
38
AUTHORS
38
AUTHORS
@ -1,6 +1,36 @@
|
||||
eekboard is written by Daiki Ueno <ueno@unixuser.org>
|
||||
eekboard is written by Daiki Ueno <ueno@unixuser.org>. The following
|
||||
files contain code derived from other free software packages:
|
||||
|
||||
Cairo keyboard drawing functions are borrowed from the libgnomekbd
|
||||
library by Sergey V. Udaltsov <svu@gnome.org>. See the comments in
|
||||
eek/eek-drawing.c for detail.
|
||||
eek/eek-keyboard-drawing.h
|
||||
eek/eek-keyboard-drawing.c
|
||||
|
||||
These files contain code derived from the libgnomekbd library.
|
||||
Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||
|
||||
eek/eek-theme.h
|
||||
eek/eek-theme.c
|
||||
eek/eek-theme-context.h
|
||||
eek/eek-theme-context.c
|
||||
eek/eek-theme-node.h
|
||||
eek/eek-theme-node.c
|
||||
|
||||
These files contain code derived from gnome-shell.
|
||||
|
||||
Copyright 2008-2010 Red Hat, Inc.
|
||||
Copyright 2009 Steve Frécinaux
|
||||
Copyright 2009, 2010 Florian Müllner
|
||||
Copyright 2010 Adel Gadllah
|
||||
Copyright 2010 Giovanni Campagna
|
||||
Copyright 2003-2004 Dodji Seketeli
|
||||
|
||||
data/icons/8x8/Makefile.am
|
||||
data/icons/16x16/Makefile.am
|
||||
data/icons/22x22/Makefile.am
|
||||
data/icons/24x24/Makefile.am
|
||||
data/icons/32x32/Makefile.am
|
||||
data/icons/48x48/Makefile.am
|
||||
data/icons/scalable/Makefile.am
|
||||
|
||||
These files contain code derived from im-chooser.
|
||||
|
||||
Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
|
||||
|
||||
2
README
2
README
@ -7,7 +7,7 @@ tools to implement desktop virtual keyboards.
|
||||
|
||||
** Dependencies
|
||||
|
||||
REQUIRED: GLib2, GTK, GConf2, PangoCairo, libxklavier
|
||||
REQUIRED: GLib2, GTK, GConf2, PangoCairo, libxklavier, libcroco
|
||||
OPTIONAL: fakekey, CSPI, Clutter, Clutter-Gtk, Vala, gobject-introspection
|
||||
|
||||
** Build from git repo
|
||||
|
||||
@ -20,7 +20,7 @@ AC_PREREQ(2.63)
|
||||
dnl AC_CONFIG_SRCDIR([configure.ac])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_INIT([eekboard], [0.90.3], [ueno@unixuser.org])
|
||||
AC_INIT([eekboard], [0.90.4], [ueno@unixuser.org])
|
||||
|
||||
dnl Init automake
|
||||
AM_INIT_AUTOMAKE
|
||||
@ -101,6 +101,8 @@ PKG_CHECK_MODULES([XKB], [x11], ,
|
||||
[AC_MSG_ERROR([XKB support not found])])
|
||||
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
|
||||
[AC_MSG_ERROR([Libxklavier not found])])
|
||||
PKG_CHECK_MODULES([LIBCROCO], [libcroco-0.6], ,
|
||||
[AC_MSG_ERROR([libcroco not found])])
|
||||
|
||||
dnl use libfakekey to generate key events
|
||||
AC_MSG_CHECKING([whether you enable fakekey])
|
||||
@ -217,7 +219,7 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Define to the read-only
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
AM_GLIB_DEFINE_LOCALEDIR(EEKBOARD_LOCALEDIR)
|
||||
|
||||
GOBJECT_INTROSPECTION_CHECK([0.6.7])
|
||||
GOBJECT_INTROSPECTION_CHECK([0.9.0])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
@ -242,6 +244,7 @@ data/icons/24x24/Makefile
|
||||
data/icons/32x32/Makefile
|
||||
data/icons/48x48/Makefile
|
||||
data/icons/scalable/Makefile
|
||||
data/themes/Makefile
|
||||
eek/eek-${EEK_API_VERSION}.pc
|
||||
eek/eek-clutter-${EEK_API_VERSION}.pc
|
||||
eek/eek-gtk-${EEK_API_VERSION}.pc
|
||||
|
||||
@ -1 +1 @@
|
||||
SUBDIRS = icons
|
||||
SUBDIRS = icons themes
|
||||
|
||||
2
data/themes/Makefile.am
Normal file
2
data/themes/Makefile.am
Normal file
@ -0,0 +1,2 @@
|
||||
themedir = $(pkgdatadir)/themes
|
||||
dist_theme_DATA = default.css
|
||||
22
data/themes/default.css
Normal file
22
data/themes/default.css
Normal file
@ -0,0 +1,22 @@
|
||||
.keyboard {
|
||||
background-color: rgba(0, 0, 0, 255);
|
||||
color: #ffffff;
|
||||
font-family: cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.key {
|
||||
color: #ffffff;
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(0, 0, 0, 255);
|
||||
background-gradient-end: rgba(64, 64, 64, 255);
|
||||
border-width: 2px;
|
||||
border-color: rgba(128, 128, 128, 255);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.key:active {
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(0, 0, 255, 255);
|
||||
background-gradient-end: rgba(64, 64, 255, 255);
|
||||
border-color: rgba(160, 160, 255, 255);
|
||||
}
|
||||
@ -39,6 +39,7 @@ libeek_public_headers = \
|
||||
$(srcdir)/eek-xml.h \
|
||||
$(srcdir)/eek-xml-layout.h \
|
||||
$(srcdir)/eek-serializable.h \
|
||||
$(srcdir)/eek-theme.h \
|
||||
$(srcdir)/eek.h
|
||||
|
||||
libeek_private_headers = \
|
||||
@ -46,7 +47,10 @@ libeek_private_headers = \
|
||||
$(srcdir)/eek-special-keysym-entries.h \
|
||||
$(srcdir)/eek-unicode-keysym-entries.h \
|
||||
$(srcdir)/eek-xkeysym-keysym-entries.h \
|
||||
$(srcdir)/eek-marshalers.h
|
||||
$(srcdir)/eek-marshalers.h \
|
||||
$(srcdir)/eek-theme-context.h \
|
||||
$(srcdir)/eek-theme-private.h \
|
||||
$(srcdir)/eek-theme-node.h
|
||||
|
||||
libeek_sources = \
|
||||
$(srcdir)/eek-layout.c \
|
||||
@ -62,7 +66,10 @@ libeek_sources = \
|
||||
$(srcdir)/eek-xml.c \
|
||||
$(srcdir)/eek-xml-layout.c \
|
||||
$(srcdir)/eek-renderer.c \
|
||||
$(srcdir)/eek-keyboard-drawing.c
|
||||
$(srcdir)/eek-keyboard-drawing.c \
|
||||
$(srcdir)/eek-theme.c \
|
||||
$(srcdir)/eek-theme-context.c \
|
||||
$(srcdir)/eek-theme-node.c
|
||||
|
||||
libeek_keysym_sources = \
|
||||
$(srcdir)/eek-special-keysym-entries.h \
|
||||
@ -85,8 +92,8 @@ libeek_la_SOURCES = \
|
||||
$(libeek_sources) \
|
||||
$(srcdir)/eek-marshalers.c
|
||||
|
||||
libeek_la_CFLAGS = $(GIO2_CFLAGS) $(PANGOCAIRO_CFLAGS)
|
||||
libeek_la_LIBADD = $(GIO2_LIBS) $(PANGOCAIRO_LIBS) -lm
|
||||
libeek_la_CFLAGS = $(GIO2_CFLAGS) $(PANGOCAIRO_CFLAGS) $(LIBCROCO_CFLAGS)
|
||||
libeek_la_LIBADD = $(GIO2_LIBS) $(PANGOCAIRO_LIBS) $(LIBCROCO_LIBS) -lm
|
||||
|
||||
if ENABLE_CLUTTER
|
||||
libeek_clutter_public_headers = \
|
||||
|
||||
@ -22,13 +22,14 @@
|
||||
* SECTION:eek-clutter-keyboard
|
||||
* @short_description: a #ClutterActor displaying #EekKeyboard
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "eek-clutter-keyboard.h"
|
||||
#include "eek-clutter-section.h"
|
||||
#include "eek-clutter-renderer.h"
|
||||
@ -49,6 +50,7 @@ struct _EekClutterKeyboardPrivate
|
||||
{
|
||||
EekKeyboard *keyboard;
|
||||
EekClutterRenderer *renderer;
|
||||
EekTheme *theme;
|
||||
};
|
||||
|
||||
struct _CreateSectionCallbackData {
|
||||
@ -77,6 +79,9 @@ eek_clutter_keyboard_real_realize (ClutterActor *self)
|
||||
|
||||
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||
|
||||
if (priv->theme)
|
||||
eek_renderer_set_theme (EEK_RENDERER(priv->renderer), priv->theme);
|
||||
|
||||
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||
clutter_actor_set_position (CLUTTER_ACTOR(self),
|
||||
bounds.x * scale,
|
||||
@ -125,7 +130,6 @@ eek_clutter_keyboard_real_allocate (ClutterActor *self,
|
||||
{
|
||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||
|
||||
g_assert (priv->renderer);
|
||||
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
|
||||
box->x2 - box->x1,
|
||||
box->y2 - box->y1);
|
||||
@ -192,6 +196,11 @@ eek_clutter_keyboard_dispose (GObject *object)
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
|
||||
if (priv->theme) {
|
||||
g_object_unref (priv->theme);
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -248,3 +257,16 @@ eek_clutter_keyboard_new (EekKeyboard *keyboard)
|
||||
{
|
||||
return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, "keyboard", keyboard, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
eek_clutter_keyboard_set_theme (EekClutterKeyboard *keyboard,
|
||||
EekTheme *theme)
|
||||
{
|
||||
EekClutterKeyboardPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEK_IS_CLUTTER_KEYBOARD(keyboard));
|
||||
g_return_if_fail (EEK_IS_THEME(theme));
|
||||
|
||||
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
priv->theme = g_object_ref (theme);
|
||||
}
|
||||
|
||||
@ -54,7 +54,9 @@ struct _EekClutterKeyboardClass
|
||||
};
|
||||
|
||||
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
|
||||
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
|
||||
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
|
||||
void eek_clutter_keyboard_set_theme (EekClutterKeyboard *keyboard,
|
||||
EekTheme *theme);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_CLUTTER_KEYBOARD_H */
|
||||
|
||||
@ -18,16 +18,16 @@
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-pango.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-clutter-renderer.h"
|
||||
#include "eek-key.h"
|
||||
|
||||
@ -77,6 +77,14 @@ cairo_pixels_to_pixbuf (guint8 *pixels,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_clutter_renderer_finalize (GObject *object)
|
||||
{
|
||||
EekClutterRendererPrivate *priv = EEK_CLUTTER_RENDERER_GET_PRIVATE(object);
|
||||
g_hash_table_destroy (priv->outline_texture_cache);
|
||||
G_OBJECT_CLASS (eek_clutter_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_clutter_renderer_class_init (EekClutterRendererClass *klass)
|
||||
{
|
||||
@ -84,6 +92,8 @@ eek_clutter_renderer_class_init (EekClutterRendererClass *klass)
|
||||
|
||||
g_type_class_add_private (gobject_class,
|
||||
sizeof (EekClutterRendererPrivate));
|
||||
|
||||
gobject_class->finalize = eek_clutter_renderer_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -109,7 +119,8 @@ eek_clutter_renderer_render_key (EekClutterRenderer *renderer,
|
||||
CoglHandle *outline_texture;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle extents = { 0, };
|
||||
CoglColor color = { 0x00, 0x00, 0x00, 0xFF };
|
||||
EekColor foreground;
|
||||
CoglColor color;
|
||||
ClutterGeometry geom;
|
||||
gulong oref;
|
||||
EekKeyboard *keyboard;
|
||||
@ -190,6 +201,17 @@ eek_clutter_renderer_render_key (EekClutterRenderer *renderer,
|
||||
layout = eek_renderer_create_pango_layout (EEK_RENDERER(renderer));
|
||||
eek_renderer_render_key_label (EEK_RENDERER(renderer), layout, key);
|
||||
pango_layout_get_extents (layout, NULL, &extents);
|
||||
|
||||
eek_renderer_get_foreground_color (EEK_RENDERER(renderer),
|
||||
EEK_ELEMENT(key),
|
||||
&foreground);
|
||||
|
||||
cogl_color_set_from_4f (&color,
|
||||
foreground.red,
|
||||
foreground.green,
|
||||
foreground.blue,
|
||||
foreground.alpha);
|
||||
|
||||
cogl_pango_render_layout (layout,
|
||||
(geom.width - extents.width / PANGO_SCALE) / 2,
|
||||
(geom.height - extents.height / PANGO_SCALE) / 2,
|
||||
|
||||
@ -26,12 +26,12 @@
|
||||
* shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "eek-element.h"
|
||||
#include "eek-container.h"
|
||||
#include "eek-marshalers.h"
|
||||
|
||||
@ -22,12 +22,13 @@
|
||||
* SECTION:eek-gtk-keyboard
|
||||
* @short_description: a #GtkWidget displaying #EekKeyboard
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "eek-gtk-keyboard.h"
|
||||
#include "eek-gtk-renderer.h"
|
||||
#include "eek-keyboard.h"
|
||||
@ -60,6 +61,7 @@ struct _EekGtkKeyboardPrivate
|
||||
gulong key_pressed_handler;
|
||||
gulong key_released_handler;
|
||||
gulong symbol_index_changed_handler;
|
||||
EekTheme *theme;
|
||||
};
|
||||
|
||||
static EekColor * color_from_gdk_color (GdkColor *gdk_color);
|
||||
@ -96,6 +98,7 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self);
|
||||
GtkAllocation allocation;
|
||||
EekColor background;
|
||||
|
||||
gtk_widget_get_allocation (self, &allocation);
|
||||
|
||||
@ -103,9 +106,12 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
GtkStyle *style;
|
||||
GtkStateType state;
|
||||
PangoContext *pcontext;
|
||||
EekColor *color;
|
||||
|
||||
pcontext = gtk_widget_get_pango_context (self);
|
||||
priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
|
||||
if (priv->theme)
|
||||
eek_renderer_set_theme (priv->renderer, priv->theme);
|
||||
|
||||
eek_renderer_set_allocation_size (priv->renderer,
|
||||
allocation.width,
|
||||
@ -114,14 +120,26 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
||||
style = gtk_widget_get_style (self);
|
||||
state = gtk_widget_get_state (self);
|
||||
|
||||
eek_renderer_set_foreground
|
||||
(priv->renderer,
|
||||
color_from_gdk_color (&style->fg[state]));
|
||||
eek_renderer_set_background
|
||||
(priv->renderer,
|
||||
color_from_gdk_color (&style->bg[state]));
|
||||
color = color_from_gdk_color (&style->fg[state]);
|
||||
eek_renderer_set_default_foreground_color (priv->renderer, color);
|
||||
eek_color_free (color);
|
||||
|
||||
color = color_from_gdk_color (&style->bg[state]);
|
||||
eek_renderer_set_default_background_color (priv->renderer, color);
|
||||
eek_color_free (color);
|
||||
}
|
||||
|
||||
/* blank background */
|
||||
eek_renderer_get_background_color (priv->renderer,
|
||||
EEK_ELEMENT(priv->keyboard),
|
||||
&background);
|
||||
cairo_set_source_rgba (cr,
|
||||
background.red,
|
||||
background.green,
|
||||
background.blue,
|
||||
background.alpha);
|
||||
cairo_paint (cr);
|
||||
|
||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||
|
||||
/* redraw dragged key */
|
||||
@ -270,7 +288,12 @@ eek_gtk_keyboard_dispose (GObject *object)
|
||||
g_object_unref (priv->keyboard);
|
||||
priv->keyboard = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (priv->theme) {
|
||||
g_object_unref (priv->theme);
|
||||
priv->theme = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -336,14 +359,10 @@ eek_gtk_keyboard_new (EekKeyboard *keyboard)
|
||||
static EekColor *
|
||||
color_from_gdk_color (GdkColor *gdk_color)
|
||||
{
|
||||
EekColor *color;
|
||||
|
||||
color = g_slice_new (EekColor);
|
||||
color->red = gdk_color->red / (gdouble)0xFFFF;
|
||||
color->green = gdk_color->green / (gdouble)0xFFFF;
|
||||
color->blue = gdk_color->blue / (gdouble)0xFFFF;
|
||||
color->alpha = 1.0;
|
||||
return color;
|
||||
return eek_color_new (gdk_color->red / (gdouble)0xFFFF,
|
||||
gdk_color->green / (gdouble)0xFFFF,
|
||||
gdk_color->blue / (gdouble)0xFFFF,
|
||||
1.0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -416,6 +435,7 @@ on_key_released (EekKeyboard *keyboard,
|
||||
large_bounds.height);
|
||||
cairo_clip (cr);
|
||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
@ -429,3 +449,16 @@ on_symbol_index_changed (EekKeyboard *keyboard,
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
void
|
||||
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
|
||||
EekTheme *theme)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
|
||||
g_return_if_fail (EEK_IS_THEME(theme));
|
||||
|
||||
priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
priv->theme = g_object_ref (theme);
|
||||
}
|
||||
|
||||
@ -55,8 +55,10 @@ struct _EekGtkKeyboardClass
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
|
||||
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
|
||||
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
|
||||
EekTheme *theme);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_GTK_KEYBOARD_H */
|
||||
|
||||
@ -99,6 +99,7 @@ eek_gtk_renderer_real_render_key_icon (EekRenderer *self,
|
||||
|
||||
eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate);
|
||||
surface = pixbuf_to_cairo_surface (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
cairo_set_source_surface (cr, surface, 0.0, 0.0);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
@ -25,15 +25,16 @@
|
||||
* The #EekKeyClass class represents a key.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#include "eek-key.h"
|
||||
#include "eek-section.h"
|
||||
#include "eek-keyboard.h"
|
||||
@ -157,6 +158,7 @@ eek_key_real_deserialize (EekSerializable *self,
|
||||
|
||||
g_variant_get_child (variant, index++, "u", &priv->keycode);
|
||||
g_variant_get_child (variant, index++, "v", &symbol_matrix);
|
||||
eek_symbol_matrix_free (priv->symbol_matrix);
|
||||
priv->symbol_matrix = _g_variant_get_symbol_matrix (symbol_matrix);
|
||||
g_variant_get_child (variant, index++, "i", &priv->column);
|
||||
g_variant_get_child (variant, index++, "i", &priv->row);
|
||||
@ -446,12 +448,14 @@ eek_key_class_init (EekKeyClass *klass)
|
||||
* @key: an #EekKey
|
||||
*
|
||||
* The ::pressed signal is emitted each time @key is shifted to
|
||||
* the pressed state.
|
||||
* the pressed state. The class handler runs before signal
|
||||
* handlers to allow signal handlers to read the status of @key
|
||||
* with eek_key_is_pressed().
|
||||
*/
|
||||
signals[PRESSED] =
|
||||
g_signal_new (I_("pressed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET(EekKeyClass, pressed),
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
@ -17,13 +17,13 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <math.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "eek-types.h"
|
||||
|
||||
static gdouble
|
||||
|
||||
@ -68,7 +68,10 @@ struct _EekKeyboardPrivate
|
||||
EekModifierBehavior modifier_behavior;
|
||||
EekModifierType modifiers;
|
||||
GArray *outline_array;
|
||||
|
||||
/* modifiers dynamically assigned at run time */
|
||||
EekModifierType num_lock_mask;
|
||||
EekModifierType alt_gr_mask;
|
||||
};
|
||||
|
||||
static EekSerializableIface *eek_keyboard_parent_serializable_iface;
|
||||
@ -165,6 +168,8 @@ eek_keyboard_real_deserialize (EekSerializable *self,
|
||||
while (g_variant_iter_next (&iter, "v", &outline)) {
|
||||
EekOutline *_outline = _g_variant_get_outline (outline);
|
||||
g_array_append_val (priv->outline_array, *_outline);
|
||||
/* don't use eek_outline_free here, so as to keep _outline->points */
|
||||
g_slice_free (EekOutline, _outline);
|
||||
}
|
||||
g_variant_get_child (variant, index++, "u", &priv->num_lock_mask);
|
||||
|
||||
@ -307,7 +312,7 @@ set_level_from_modifiers (EekKeyboard *self)
|
||||
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
|
||||
gint level = 0;
|
||||
|
||||
if (priv->modifiers & EEK_MOD5_MASK)
|
||||
if (priv->modifiers & priv->alt_gr_mask)
|
||||
level |= 2;
|
||||
if (priv->modifiers & EEK_SHIFT_MASK)
|
||||
level |= 1;
|
||||
@ -327,18 +332,10 @@ eek_keyboard_real_key_pressed (EekKeyboard *self,
|
||||
return;
|
||||
|
||||
modifier = eek_symbol_get_modifier_mask (symbol);
|
||||
switch (priv->modifier_behavior) {
|
||||
case EEK_MODIFIER_BEHAVIOR_NONE:
|
||||
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
|
||||
priv->modifiers |= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LOCK:
|
||||
priv->modifiers ^= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LATCH:
|
||||
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
|
||||
break;
|
||||
set_level_from_modifiers (self);
|
||||
}
|
||||
set_level_from_modifiers (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -354,9 +351,16 @@ eek_keyboard_real_key_released (EekKeyboard *self,
|
||||
return;
|
||||
|
||||
modifier = eek_symbol_get_modifier_mask (symbol);
|
||||
if (modifier != 0) {
|
||||
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE)
|
||||
priv->modifiers &= ~modifier;
|
||||
switch (priv->modifier_behavior) {
|
||||
case EEK_MODIFIER_BEHAVIOR_NONE:
|
||||
priv->modifiers &= ~modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LOCK:
|
||||
priv->modifiers ^= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LATCH:
|
||||
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
|
||||
break;
|
||||
}
|
||||
set_level_from_modifiers (self);
|
||||
}
|
||||
@ -775,6 +779,8 @@ eek_keyboard_add_outline (EekKeyboard *keyboard,
|
||||
|
||||
_outline = eek_outline_copy (outline);
|
||||
g_array_append_val (priv->outline_array, *_outline);
|
||||
/* don't use eek_outline_free here, so as to keep _outline->points */
|
||||
g_slice_free (EekOutline, _outline);
|
||||
return priv->outline_array->len;
|
||||
}
|
||||
|
||||
@ -801,6 +807,13 @@ eek_keyboard_get_outline (EekKeyboard *keyboard,
|
||||
return &g_array_index (priv->outline_array, EekOutline, oref - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_keyboard_set_num_lock_mask:
|
||||
* @keyboard: an #EekKeyboard
|
||||
* @num_lock_mask: an #EekModifierType
|
||||
*
|
||||
* Set modifier mask used as Num_Lock.
|
||||
*/
|
||||
void
|
||||
eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard,
|
||||
EekModifierType num_lock_mask)
|
||||
@ -813,6 +826,13 @@ eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard,
|
||||
priv->num_lock_mask = num_lock_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_keyboard_get_num_lock_mask:
|
||||
* @keyboard: an #EekKeyboard
|
||||
*
|
||||
* Get modifier mask used as Num_Lock.
|
||||
* Returns: an #EekModifierType
|
||||
*/
|
||||
EekModifierType
|
||||
eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
|
||||
{
|
||||
@ -823,3 +843,40 @@ eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
|
||||
|
||||
return priv->num_lock_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_keyboard_set_alt_gr_mask:
|
||||
* @keyboard: an #EekKeyboard
|
||||
* @alt_gr_mask: an #EekModifierType
|
||||
*
|
||||
* Set modifier mask used as Alt_Gr.
|
||||
*/
|
||||
void
|
||||
eek_keyboard_set_alt_gr_mask (EekKeyboard *keyboard,
|
||||
EekModifierType alt_gr_mask)
|
||||
{
|
||||
EekKeyboardPrivate *priv;
|
||||
|
||||
g_assert (EEK_IS_KEYBOARD(keyboard));
|
||||
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
|
||||
priv->alt_gr_mask = alt_gr_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_keyboard_get_alt_gr_mask:
|
||||
* @keyboard: an #EekKeyboard
|
||||
*
|
||||
* Get modifier mask used as Alt_Gr.
|
||||
* Returns: an #EekModifierType
|
||||
*/
|
||||
EekModifierType
|
||||
eek_keyboard_get_alt_gr_mask (EekKeyboard *keyboard)
|
||||
{
|
||||
EekKeyboardPrivate *priv;
|
||||
|
||||
g_assert (EEK_IS_KEYBOARD(keyboard));
|
||||
priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
|
||||
return priv->alt_gr_mask;
|
||||
}
|
||||
|
||||
@ -153,5 +153,11 @@ void eek_keyboard_set_num_lock_mask
|
||||
EekModifierType eek_keyboard_get_num_lock_mask
|
||||
(EekKeyboard *keyboard);
|
||||
|
||||
void eek_keyboard_set_alt_gr_mask
|
||||
(EekKeyboard *keyboard,
|
||||
EekModifierType alt_gr_mask);
|
||||
EekModifierType eek_keyboard_get_alt_gr_mask
|
||||
(EekKeyboard *keyboard);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_KEYBOARD_H */
|
||||
|
||||
@ -23,13 +23,13 @@
|
||||
* @short_description: an #EekSymbol represents an X keysym
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "eek-keysym.h"
|
||||
#include "eek-serializable.h"
|
||||
|
||||
|
||||
@ -18,12 +18,12 @@
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "eek-key.h"
|
||||
#include "eek-section.h"
|
||||
#include "eek-renderer.h"
|
||||
@ -45,17 +45,26 @@ struct _EekRendererPrivate
|
||||
EekKeyboard *keyboard;
|
||||
PangoContext *pcontext;
|
||||
|
||||
EekColor *foreground;
|
||||
EekColor *background;
|
||||
EekColor default_foreground_color;
|
||||
EekColor default_background_color;
|
||||
gdouble border_width;
|
||||
|
||||
gdouble allocation_width;
|
||||
gdouble allocation_height;
|
||||
gdouble scale;
|
||||
|
||||
PangoFontDescription *font;
|
||||
GHashTable *outline_surface_cache;
|
||||
GHashTable *active_outline_surface_cache;
|
||||
cairo_surface_t *keyboard_surface;
|
||||
gulong symbol_index_changed_handler;
|
||||
|
||||
EekTheme *theme;
|
||||
};
|
||||
|
||||
static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0};
|
||||
static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
struct {
|
||||
gint category;
|
||||
gdouble scale;
|
||||
@ -144,6 +153,14 @@ create_keyboard_surface (EekRenderer *renderer)
|
||||
EekBounds bounds;
|
||||
cairo_surface_t *keyboard_surface;
|
||||
CreateKeyboardSurfaceCallbackData data;
|
||||
EekColor foreground, background;
|
||||
|
||||
eek_renderer_get_foreground_color (renderer,
|
||||
EEK_ELEMENT(priv->keyboard),
|
||||
&foreground);
|
||||
eek_renderer_get_background_color (renderer,
|
||||
EEK_ELEMENT(priv->keyboard),
|
||||
&background);
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
|
||||
keyboard_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
@ -156,22 +173,24 @@ create_keyboard_surface (EekRenderer *renderer)
|
||||
|
||||
/* blank background */
|
||||
cairo_set_source_rgba (data.cr,
|
||||
priv->background->red,
|
||||
priv->background->green,
|
||||
priv->background->blue,
|
||||
priv->background->alpha);
|
||||
cairo_rectangle (data.cr,
|
||||
0.0,
|
||||
0.0,
|
||||
cairo_image_surface_get_width (keyboard_surface),
|
||||
cairo_image_surface_get_height (keyboard_surface));
|
||||
cairo_fill (data.cr);
|
||||
background.red,
|
||||
background.green,
|
||||
background.blue,
|
||||
background.alpha);
|
||||
cairo_paint (data.cr);
|
||||
|
||||
cairo_set_source_rgba (data.cr,
|
||||
foreground.red,
|
||||
foreground.green,
|
||||
foreground.blue,
|
||||
foreground.alpha);
|
||||
|
||||
/* draw sections */
|
||||
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
||||
create_keyboard_surface_section_callback,
|
||||
&data);
|
||||
cairo_destroy (data.cr);
|
||||
|
||||
return keyboard_surface;
|
||||
}
|
||||
|
||||
@ -183,21 +202,54 @@ render_key_outline (EekRenderer *renderer,
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
EekOutline *outline;
|
||||
EekBounds bounds;
|
||||
cairo_pattern_t *pat;
|
||||
gdouble scale;
|
||||
gint i;
|
||||
gulong oref;
|
||||
|
||||
/* need to rescale so that the border fit inside the clipping
|
||||
region */
|
||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||
scale = MIN((bounds.width - priv->border_width) / bounds.width,
|
||||
(bounds.height - priv->border_width) / bounds.height);
|
||||
EekThemeNode *theme_node;
|
||||
EekColor foreground, background, gradient_start, gradient_end, border_color;
|
||||
EekGradientType gradient_type;
|
||||
gint border_width;
|
||||
gint border_radius;
|
||||
|
||||
oref = eek_key_get_oref (key);
|
||||
if (oref == 0)
|
||||
return;
|
||||
|
||||
if (eek_key_is_pressed (key))
|
||||
theme_node = g_object_get_data (G_OBJECT(key), "theme-node-pressed");
|
||||
else
|
||||
theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
|
||||
if (theme_node) {
|
||||
eek_theme_node_get_foreground_color (theme_node, &foreground);
|
||||
eek_theme_node_get_background_color (theme_node, &background);
|
||||
eek_theme_node_get_background_gradient (theme_node,
|
||||
&gradient_type,
|
||||
&gradient_start,
|
||||
&gradient_end);
|
||||
border_width = eek_theme_node_get_border_width (theme_node,
|
||||
EEK_SIDE_TOP);
|
||||
border_radius = eek_theme_node_get_border_radius (theme_node,
|
||||
EEK_SIDE_TOP);
|
||||
eek_theme_node_get_border_color (theme_node, EEK_SIDE_TOP,
|
||||
&border_color);
|
||||
} else {
|
||||
foreground = priv->default_foreground_color;
|
||||
background = priv->default_background_color;
|
||||
gradient_type = EEK_GRADIENT_NONE;
|
||||
border_width = priv->border_width;
|
||||
border_radius = -1;
|
||||
border_color.red = ABS(background.red - foreground.red) * 0.7;
|
||||
border_color.green = ABS(background.green - foreground.green) * 0.7;
|
||||
border_color.blue = ABS(background.blue - foreground.blue) * 0.7;
|
||||
border_color.alpha = foreground.alpha;
|
||||
}
|
||||
|
||||
/* need to rescale so that the border fit inside the clipping
|
||||
region */
|
||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||
scale = MIN((bounds.width - border_width) / bounds.width,
|
||||
(bounds.height - border_width) / bounds.height);
|
||||
|
||||
outline = eek_keyboard_get_outline (priv->keyboard, oref);
|
||||
outline = eek_outline_copy (outline);
|
||||
for (i = 0; i < outline->num_points; i++) {
|
||||
@ -206,49 +258,81 @@ render_key_outline (EekRenderer *renderer,
|
||||
}
|
||||
|
||||
cairo_translate (cr,
|
||||
priv->border_width / 2 * priv->scale,
|
||||
priv->border_width / 2 * priv->scale);
|
||||
border_width / 2 * priv->scale,
|
||||
border_width / 2 * priv->scale);
|
||||
|
||||
/* paint the background with gradient */
|
||||
pat = cairo_pattern_create_linear (0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
bounds.height * priv->scale * 5.0);
|
||||
cairo_pattern_add_color_stop_rgba (pat,
|
||||
1,
|
||||
priv->background->red * 0.5,
|
||||
priv->background->green * 0.5,
|
||||
priv->background->blue * 0.5,
|
||||
priv->background->alpha);
|
||||
cairo_pattern_add_color_stop_rgba (pat,
|
||||
0,
|
||||
priv->background->red,
|
||||
priv->background->green,
|
||||
priv->background->blue,
|
||||
priv->background->alpha);
|
||||
if (gradient_type != EEK_GRADIENT_NONE) {
|
||||
cairo_pattern_t *pat;
|
||||
gdouble cx, cy;
|
||||
|
||||
switch (gradient_type) {
|
||||
case EEK_GRADIENT_VERTICAL:
|
||||
pat = cairo_pattern_create_linear (0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
bounds.height * priv->scale);
|
||||
break;
|
||||
case EEK_GRADIENT_HORIZONTAL:
|
||||
pat = cairo_pattern_create_linear (0.0,
|
||||
0.0,
|
||||
bounds.width * priv->scale,
|
||||
0.0);
|
||||
break;
|
||||
case EEK_GRADIENT_RADIAL:
|
||||
cx = bounds.width / 2 * priv->scale;
|
||||
cy = bounds.height / 2 * priv->scale;
|
||||
pat = cairo_pattern_create_radial (cx,
|
||||
cy,
|
||||
0,
|
||||
cx,
|
||||
cy,
|
||||
MIN(cx, cy));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_pattern_add_color_stop_rgba (pat,
|
||||
1,
|
||||
gradient_start.red * 0.5,
|
||||
gradient_start.green * 0.5,
|
||||
gradient_start.blue * 0.5,
|
||||
gradient_start.alpha);
|
||||
cairo_pattern_add_color_stop_rgba (pat,
|
||||
0,
|
||||
gradient_end.red,
|
||||
gradient_end.green,
|
||||
gradient_end.blue,
|
||||
gradient_end.alpha);
|
||||
cairo_set_source (cr, pat);
|
||||
cairo_pattern_destroy (pat);
|
||||
} else {
|
||||
cairo_set_source_rgba (cr,
|
||||
background.red,
|
||||
background.green,
|
||||
background.blue,
|
||||
background.alpha);
|
||||
}
|
||||
|
||||
cairo_set_source (cr, pat);
|
||||
_eek_rounded_polygon (cr,
|
||||
outline->corner_radius,
|
||||
border_radius >= 0 ? border_radius : outline->corner_radius,
|
||||
outline->points,
|
||||
outline->num_points);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pat);
|
||||
|
||||
/* paint the border */
|
||||
cairo_set_line_width (cr, priv->border_width);
|
||||
cairo_set_line_width (cr, border_width);
|
||||
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
||||
|
||||
cairo_set_source_rgba
|
||||
(cr,
|
||||
ABS(priv->background->red - priv->foreground->red) * 0.7,
|
||||
ABS(priv->background->green - priv->foreground->green) * 0.7,
|
||||
ABS(priv->background->blue - priv->foreground->blue) * 0.7,
|
||||
priv->foreground->alpha);
|
||||
cairo_set_source_rgba (cr,
|
||||
border_color.red,
|
||||
border_color.green,
|
||||
border_color.blue,
|
||||
border_color.alpha);
|
||||
|
||||
_eek_rounded_polygon (cr,
|
||||
outline->corner_radius,
|
||||
border_radius >= 0 ? border_radius : outline->corner_radius,
|
||||
outline->points,
|
||||
outline->num_points);
|
||||
cairo_stroke (cr);
|
||||
@ -260,6 +344,7 @@ struct _CalculateFontSizeCallbackData {
|
||||
gdouble size;
|
||||
gdouble em_size;
|
||||
EekRenderer *renderer;
|
||||
const PangoFontDescription *base_font;
|
||||
};
|
||||
typedef struct _CalculateFontSizeCallbackData CalculateFontSizeCallbackData;
|
||||
|
||||
@ -270,7 +355,6 @@ calculate_font_size_key_callback (EekElement *element, gpointer user_data)
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
|
||||
gdouble sx, sy;
|
||||
PangoFontDescription *font;
|
||||
const PangoFontDescription *base_font;
|
||||
PangoRectangle extents = { 0, };
|
||||
PangoLayout *layout;
|
||||
gdouble size;
|
||||
@ -285,8 +369,7 @@ calculate_font_size_key_callback (EekElement *element, gpointer user_data)
|
||||
if (!label)
|
||||
label = "M";
|
||||
|
||||
base_font = pango_context_get_font_description (priv->pcontext);
|
||||
font = pango_font_description_copy (base_font);
|
||||
font = pango_font_description_copy (data->base_font);
|
||||
|
||||
eek_element_get_bounds (element, &bounds);
|
||||
size = eek_bounds_long_side (&bounds) * PANGO_SCALE;
|
||||
@ -307,7 +390,7 @@ calculate_font_size_key_callback (EekElement *element, gpointer user_data)
|
||||
sy = bounds.height * PANGO_SCALE / extents.height;
|
||||
|
||||
size *= MIN(sx, sy);
|
||||
if (size >= pango_font_description_get_size (base_font)) {
|
||||
if (size >= pango_font_description_get_size (data->base_font)) {
|
||||
if (size < data->size)
|
||||
data->size = size;
|
||||
if (size < data->em_size)
|
||||
@ -324,16 +407,15 @@ calculate_font_size_section_callback (EekElement *element, gpointer user_data)
|
||||
}
|
||||
|
||||
static gdouble
|
||||
calculate_font_size (EekRenderer *renderer)
|
||||
calculate_font_size (EekRenderer *renderer, const PangoFontDescription *base_font)
|
||||
{
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
CalculateFontSizeCallbackData data;
|
||||
PangoFontDescription *base_font;
|
||||
|
||||
base_font = pango_context_get_font_description (priv->pcontext);
|
||||
data.size = G_MAXDOUBLE;
|
||||
data.em_size = G_MAXDOUBLE;
|
||||
data.renderer = renderer;
|
||||
data.base_font = base_font;
|
||||
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
||||
calculate_font_size_section_callback,
|
||||
&data);
|
||||
@ -351,15 +433,20 @@ render_key (EekRenderer *self,
|
||||
EekBounds bounds;
|
||||
gulong oref;
|
||||
EekSymbol *symbol;
|
||||
GHashTable *outline_surface_cache;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||
oref = eek_key_get_oref (key);
|
||||
if (oref == 0)
|
||||
return;
|
||||
|
||||
if (eek_key_is_pressed (key))
|
||||
outline_surface_cache = priv->active_outline_surface_cache;
|
||||
else
|
||||
outline_surface_cache = priv->outline_surface_cache;
|
||||
|
||||
outline = eek_keyboard_get_outline (priv->keyboard, oref);
|
||||
outline_surface = g_hash_table_lookup (priv->outline_surface_cache,
|
||||
outline);
|
||||
outline_surface = g_hash_table_lookup (outline_surface_cache, outline);
|
||||
if (!outline_surface) {
|
||||
cairo_t *cr;
|
||||
|
||||
@ -370,18 +457,13 @@ render_key (EekRenderer *self,
|
||||
cr = cairo_create (outline_surface);
|
||||
|
||||
/* blank background */
|
||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_rectangle (cr,
|
||||
0.0,
|
||||
0.0,
|
||||
bounds.width * priv->scale,
|
||||
bounds.height * priv->scale);
|
||||
cairo_fill (cr);
|
||||
cairo_paint (cr);
|
||||
|
||||
eek_renderer_render_key_outline (self, cr, key, 1.0, 0);
|
||||
cairo_destroy (cr);
|
||||
|
||||
g_hash_table_insert (priv->outline_surface_cache,
|
||||
g_hash_table_insert (outline_surface_cache,
|
||||
outline,
|
||||
outline_surface);
|
||||
}
|
||||
@ -396,6 +478,8 @@ render_key (EekRenderer *self,
|
||||
} else {
|
||||
PangoLayout *layout;
|
||||
PangoRectangle extents = { 0, };
|
||||
EekColor foreground;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
layout = pango_cairo_create_layout (cr);
|
||||
eek_renderer_render_key_label (self, layout, key);
|
||||
@ -406,11 +490,18 @@ render_key (EekRenderer *self,
|
||||
(cr,
|
||||
(bounds.width * priv->scale - extents.width / PANGO_SCALE) / 2,
|
||||
(bounds.height * priv->scale - extents.height / PANGO_SCALE) / 2);
|
||||
|
||||
if (eek_key_is_pressed (key))
|
||||
theme_node = g_object_get_data (G_OBJECT(key), "theme-node-pressed");
|
||||
else
|
||||
theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
|
||||
|
||||
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
|
||||
cairo_set_source_rgba (cr,
|
||||
priv->foreground->red,
|
||||
priv->foreground->green,
|
||||
priv->foreground->blue,
|
||||
priv->foreground->alpha);
|
||||
foreground.red,
|
||||
foreground.green,
|
||||
foreground.blue,
|
||||
foreground.alpha);
|
||||
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
cairo_restore (cr);
|
||||
@ -470,11 +561,16 @@ eek_renderer_real_render_key_label (EekRenderer *self,
|
||||
return;
|
||||
|
||||
if (!priv->font) {
|
||||
PangoFontDescription *base_font;
|
||||
const PangoFontDescription *base_font;
|
||||
gdouble size;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
size = calculate_font_size (self);
|
||||
base_font = pango_context_get_font_description (priv->pcontext);
|
||||
theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
|
||||
if (theme_node)
|
||||
base_font = eek_theme_node_get_font (theme_node);
|
||||
else
|
||||
base_font = pango_context_get_font_description (priv->pcontext);
|
||||
size = calculate_font_size (self, base_font);
|
||||
priv->font = pango_font_description_copy (base_font);
|
||||
pango_font_description_set_size (priv->font, size);
|
||||
}
|
||||
@ -493,6 +589,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
|
||||
}
|
||||
pango_font_description_set_size (font, size * priv->scale * scale);
|
||||
pango_layout_set_font_description (layout, font);
|
||||
pango_font_description_free (font);
|
||||
pango_layout_set_text (layout, label, -1);
|
||||
pango_layout_set_width (layout,
|
||||
PANGO_SCALE * bounds.width * priv->scale * scale);
|
||||
@ -531,6 +628,10 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
|
||||
{
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
|
||||
|
||||
g_return_if_fail (priv->keyboard);
|
||||
g_return_if_fail (priv->allocation_width > 0.0);
|
||||
g_return_if_fail (priv->allocation_height > 0.0);
|
||||
|
||||
if (!priv->keyboard_surface)
|
||||
priv->keyboard_surface = create_keyboard_surface (self);
|
||||
|
||||
@ -560,6 +661,31 @@ eek_renderer_set_property (GObject *object,
|
||||
priv->pcontext = g_value_get_object (value);
|
||||
g_object_ref (priv->pcontext);
|
||||
break;
|
||||
default:
|
||||
g_object_set_property (object,
|
||||
g_param_spec_get_name (pspec),
|
||||
value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_KEYBOARD:
|
||||
g_value_set_object (value, priv->keyboard);
|
||||
break;
|
||||
default:
|
||||
g_object_get_property (object,
|
||||
g_param_spec_get_name (pspec),
|
||||
value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -592,6 +718,8 @@ eek_renderer_finalize (GObject *object)
|
||||
{
|
||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
|
||||
g_hash_table_destroy (priv->outline_surface_cache);
|
||||
g_hash_table_destroy (priv->active_outline_surface_cache);
|
||||
pango_font_description_free (priv->font);
|
||||
G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@ -610,6 +738,7 @@ eek_renderer_class_init (EekRendererClass *klass)
|
||||
klass->render_keyboard = eek_renderer_real_render_keyboard;
|
||||
|
||||
gobject_class->set_property = eek_renderer_set_property;
|
||||
gobject_class->get_property = eek_renderer_get_property;
|
||||
gobject_class->dispose = eek_renderer_dispose;
|
||||
gobject_class->finalize = eek_renderer_finalize;
|
||||
|
||||
@ -617,7 +746,7 @@ eek_renderer_class_init (EekRendererClass *klass)
|
||||
"Keyboard",
|
||||
"Keyboard",
|
||||
EEK_TYPE_KEYBOARD,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_KEYBOARD,
|
||||
pspec);
|
||||
@ -632,12 +761,6 @@ eek_renderer_class_init (EekRendererClass *klass)
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
free_surface (gpointer data)
|
||||
{
|
||||
cairo_surface_destroy (data);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_renderer_init (EekRenderer *self)
|
||||
{
|
||||
@ -646,16 +769,23 @@ eek_renderer_init (EekRenderer *self)
|
||||
priv = self->priv = EEK_RENDERER_GET_PRIVATE(self);
|
||||
priv->keyboard = NULL;
|
||||
priv->pcontext = NULL;
|
||||
priv->foreground = eek_color_new (0.3, 0.3, 0.3, 1.0);
|
||||
priv->background = eek_color_new (1.0, 1.0, 1.0, 1.0);
|
||||
priv->default_foreground_color = DEFAULT_FOREGROUND_COLOR;
|
||||
priv->default_background_color = DEFAULT_BACKGROUND_COLOR;
|
||||
priv->border_width = 1.0;
|
||||
priv->allocation_width = 0.0;
|
||||
priv->allocation_height = 0.0;
|
||||
priv->scale = 1.0;
|
||||
priv->font = NULL;
|
||||
priv->outline_surface_cache =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
free_surface);
|
||||
(GDestroyNotify)cairo_surface_destroy);
|
||||
priv->active_outline_surface_cache =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
NULL,
|
||||
(GDestroyNotify)cairo_surface_destroy);
|
||||
priv->keyboard_surface = NULL;
|
||||
priv->symbol_index_changed_handler = 0;
|
||||
}
|
||||
@ -668,6 +798,9 @@ invalidate (EekRenderer *renderer)
|
||||
if (priv->outline_surface_cache)
|
||||
g_hash_table_remove_all (priv->outline_surface_cache);
|
||||
|
||||
if (priv->active_outline_surface_cache)
|
||||
g_hash_table_remove_all (priv->active_outline_surface_cache);
|
||||
|
||||
if (priv->keyboard_surface) {
|
||||
cairo_surface_destroy (priv->keyboard_surface);
|
||||
priv->keyboard_surface = NULL;
|
||||
@ -712,6 +845,9 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
|
||||
priv->allocation_width = width;
|
||||
priv->allocation_height = height;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
|
||||
scale = width > height ? height / bounds.height :
|
||||
width / bounds.width;
|
||||
@ -906,55 +1042,94 @@ eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_foreground (EekRenderer *renderer,
|
||||
EekColor *foreground)
|
||||
eek_renderer_set_default_foreground_color (EekRenderer *renderer,
|
||||
const EekColor *color)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (foreground);
|
||||
g_return_if_fail (color);
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
priv->foreground = g_boxed_copy (EEK_TYPE_COLOR, foreground);
|
||||
priv->default_foreground_color = *color;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_background (EekRenderer *renderer,
|
||||
EekColor *background)
|
||||
eek_renderer_set_default_background_color (EekRenderer *renderer,
|
||||
const EekColor *color)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (background);
|
||||
g_return_if_fail (color);
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
priv->background = g_boxed_copy (EEK_TYPE_COLOR, background);
|
||||
priv->default_background_color = *color;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_get_foreground (EekRenderer *renderer,
|
||||
EekColor *foreground)
|
||||
eek_renderer_get_foreground_color (EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekColor *color)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (foreground);
|
||||
g_return_if_fail (color);
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
*foreground = *priv->foreground;
|
||||
|
||||
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
|
||||
if (theme_node)
|
||||
eek_theme_node_get_foreground_color (theme_node, color);
|
||||
else
|
||||
*color = priv->default_foreground_color;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_get_background (EekRenderer *renderer,
|
||||
EekColor *background)
|
||||
eek_renderer_get_background_color (EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekColor *color)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (background);
|
||||
g_return_if_fail (color);
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
*background = *priv->background;
|
||||
|
||||
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
|
||||
if (theme_node)
|
||||
eek_theme_node_get_background_color (theme_node, color);
|
||||
else
|
||||
*color = priv->default_background_color;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_get_background_gradient (EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekGradientType *type,
|
||||
EekColor *start,
|
||||
EekColor *end)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||
g_return_if_fail (EEK_IS_ELEMENT(element));
|
||||
g_return_if_fail (type);
|
||||
g_return_if_fail (start);
|
||||
g_return_if_fail (end);
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
|
||||
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
|
||||
if (theme_node)
|
||||
eek_theme_node_get_background_gradient (theme_node, type, start, end);
|
||||
else
|
||||
*type = EEK_GRADIENT_NONE;
|
||||
}
|
||||
|
||||
struct _FindKeyByPositionCallbackData {
|
||||
@ -1082,3 +1257,119 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
|
||||
&data);
|
||||
return data.key;
|
||||
}
|
||||
|
||||
struct _CreateThemeNodeData {
|
||||
EekThemeContext *context;
|
||||
EekThemeNode *parent;
|
||||
EekRenderer *renderer;
|
||||
};
|
||||
typedef struct _CreateThemeNodeData CreateThemeNodeData;
|
||||
|
||||
void
|
||||
create_theme_node_key_callback (EekElement *element,
|
||||
gpointer user_data)
|
||||
{
|
||||
CreateThemeNodeData *data = user_data;
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeNode *theme_node;
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
|
||||
|
||||
theme_node = eek_theme_node_new (data->context,
|
||||
data->parent,
|
||||
priv->theme,
|
||||
EEK_TYPE_KEY,
|
||||
eek_element_get_name (element),
|
||||
"key",
|
||||
NULL,
|
||||
NULL);
|
||||
g_object_set_data_full (G_OBJECT(element),
|
||||
"theme-node",
|
||||
theme_node,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
|
||||
theme_node = eek_theme_node_new (data->context,
|
||||
data->parent,
|
||||
priv->theme,
|
||||
EEK_TYPE_KEY,
|
||||
eek_element_get_name (element),
|
||||
"key",
|
||||
"active",
|
||||
NULL);
|
||||
g_object_set_data_full (G_OBJECT(element),
|
||||
"theme-node-pressed",
|
||||
theme_node,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
create_theme_node_section_callback (EekElement *element,
|
||||
gpointer user_data)
|
||||
{
|
||||
CreateThemeNodeData *data = user_data;
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeNode *theme_node, *parent;
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
|
||||
|
||||
theme_node = eek_theme_node_new (data->context,
|
||||
data->parent,
|
||||
priv->theme,
|
||||
EEK_TYPE_SECTION,
|
||||
eek_element_get_name (element),
|
||||
"section",
|
||||
NULL,
|
||||
NULL);
|
||||
g_object_set_data_full (G_OBJECT(element),
|
||||
"theme-node",
|
||||
theme_node,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
|
||||
parent = data->parent;
|
||||
data->parent = theme_node;
|
||||
eek_container_foreach_child (EEK_CONTAINER(element),
|
||||
create_theme_node_key_callback,
|
||||
data);
|
||||
data->parent = parent;
|
||||
}
|
||||
|
||||
void
|
||||
eek_renderer_set_theme (EekRenderer *renderer,
|
||||
EekTheme *theme)
|
||||
{
|
||||
EekRendererPrivate *priv;
|
||||
EekThemeContext *theme_context;
|
||||
EekThemeNode *theme_node;
|
||||
CreateThemeNodeData data;
|
||||
|
||||
g_assert (EEK_IS_RENDERER(renderer));
|
||||
g_assert (EEK_IS_THEME(theme));
|
||||
|
||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||
g_assert (priv->keyboard);
|
||||
|
||||
if (priv->theme)
|
||||
g_object_unref (priv->theme);
|
||||
priv->theme = g_object_ref (theme);
|
||||
|
||||
theme_context = eek_theme_context_new ();
|
||||
theme_node = eek_theme_node_new (theme_context,
|
||||
NULL,
|
||||
priv->theme,
|
||||
EEK_TYPE_KEYBOARD,
|
||||
"keyboard",
|
||||
"keyboard",
|
||||
NULL,
|
||||
NULL);
|
||||
g_object_set_data_full (G_OBJECT(priv->keyboard),
|
||||
"theme-node",
|
||||
theme_node,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
|
||||
data.context = theme_context;
|
||||
data.parent = theme_node;
|
||||
data.renderer = renderer;
|
||||
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
||||
create_theme_node_section_callback,
|
||||
&data);
|
||||
}
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-keysym.h"
|
||||
#include "eek-types.h"
|
||||
#include "eek-theme.h"
|
||||
#include "eek-theme-context.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -80,66 +82,79 @@ struct _EekRendererClass
|
||||
};
|
||||
|
||||
GType eek_renderer_get_type (void) G_GNUC_CONST;
|
||||
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
|
||||
PangoContext *pcontext);
|
||||
void eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
void eek_renderer_get_size (EekRenderer *renderer,
|
||||
gdouble *width,
|
||||
gdouble *height);
|
||||
void eek_renderer_get_key_bounds (EekRenderer *renderer,
|
||||
EekKey *key,
|
||||
EekBounds *bounds,
|
||||
gboolean rotate);
|
||||
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
|
||||
PangoContext *pcontext);
|
||||
void eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
void eek_renderer_get_size (EekRenderer *renderer,
|
||||
gdouble *width,
|
||||
gdouble *height);
|
||||
void eek_renderer_get_key_bounds (EekRenderer *renderer,
|
||||
EekKey *key,
|
||||
EekBounds *bounds,
|
||||
gboolean rotate);
|
||||
|
||||
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
||||
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
||||
|
||||
PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer);
|
||||
void eek_renderer_render_key_label (EekRenderer *renderer,
|
||||
PangoLayout *layout,
|
||||
EekKey *key);
|
||||
PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer);
|
||||
void eek_renderer_render_key_label (EekRenderer *renderer,
|
||||
PangoLayout *layout,
|
||||
EekKey *key);
|
||||
|
||||
void eek_renderer_render_key_outline (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
void eek_renderer_render_key_outline (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
void eek_renderer_render_key (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
void eek_renderer_render_key (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
void eek_renderer_render_key_icon (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
void eek_renderer_render_key_icon (EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
cairo_t *cr);
|
||||
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||
cairo_t *cr);
|
||||
|
||||
void eek_renderer_set_foreground (EekRenderer *renderer,
|
||||
EekColor *foreground);
|
||||
void eek_renderer_set_background (EekRenderer *renderer,
|
||||
EekColor *background);
|
||||
void eek_renderer_get_foreground (EekRenderer *renderer,
|
||||
EekColor *foreground);
|
||||
void eek_renderer_get_background (EekRenderer *renderer,
|
||||
EekColor *background);
|
||||
void eek_renderer_set_border_width (EekRenderer *renderer,
|
||||
gdouble border_width);
|
||||
EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void eek_renderer_set_default_foreground_color
|
||||
(EekRenderer *renderer,
|
||||
const EekColor *color);
|
||||
void eek_renderer_set_default_background_color
|
||||
(EekRenderer *renderer,
|
||||
const EekColor *color);
|
||||
void eek_renderer_get_foreground_color (EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekColor *color);
|
||||
void eek_renderer_get_background_color (EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekColor *color);
|
||||
void eek_renderer_get_background_gradient
|
||||
(EekRenderer *renderer,
|
||||
EekElement *element,
|
||||
EekGradientType *type,
|
||||
EekColor *start,
|
||||
EekColor *end);
|
||||
void eek_renderer_set_border_width (EekRenderer *renderer,
|
||||
gdouble border_width);
|
||||
EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void eek_renderer_apply_transformation_for_key
|
||||
(EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
(EekRenderer *renderer,
|
||||
cairo_t *cr,
|
||||
EekKey *key,
|
||||
gdouble scale,
|
||||
gboolean rotate);
|
||||
|
||||
void eek_renderer_set_theme (EekRenderer *renderer,
|
||||
EekTheme *theme);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_RENDERER_H */
|
||||
|
||||
@ -27,11 +27,12 @@
|
||||
* of one or more keys of the #EekKeyClass class.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-section.h"
|
||||
#include "eek-key.h"
|
||||
@ -265,6 +266,21 @@ eek_section_real_find_key_by_keycode (EekSection *self,
|
||||
(gpointer)(long)keycode);
|
||||
}
|
||||
|
||||
static void
|
||||
set_level_from_modifiers (EekSection *self)
|
||||
{
|
||||
EekSectionPrivate *priv = EEK_SECTION_GET_PRIVATE(self);
|
||||
EekKeyboard *keyboard;
|
||||
EekModifierType num_lock_mask;
|
||||
gint level = -1;
|
||||
|
||||
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
|
||||
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
|
||||
if (priv->modifiers & num_lock_mask)
|
||||
level = 1;
|
||||
eek_element_set_level (EEK_ELEMENT(self), level);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_section_real_key_pressed (EekSection *self, EekKey *key)
|
||||
{
|
||||
@ -273,8 +289,6 @@ eek_section_real_key_pressed (EekSection *self, EekKey *key)
|
||||
EekKeyboard *keyboard;
|
||||
EekModifierBehavior behavior;
|
||||
EekModifierType modifier;
|
||||
EekModifierType num_lock_mask;
|
||||
gint level = -1;
|
||||
|
||||
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
|
||||
if (!symbol)
|
||||
@ -283,22 +297,10 @@ eek_section_real_key_pressed (EekSection *self, EekKey *key)
|
||||
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
|
||||
behavior = eek_keyboard_get_modifier_behavior (keyboard);
|
||||
modifier = eek_symbol_get_modifier_mask (symbol);
|
||||
switch (behavior) {
|
||||
case EEK_MODIFIER_BEHAVIOR_NONE:
|
||||
if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
|
||||
priv->modifiers |= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LOCK:
|
||||
priv->modifiers ^= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LATCH:
|
||||
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
|
||||
break;
|
||||
set_level_from_modifiers (self);
|
||||
}
|
||||
|
||||
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
|
||||
if (priv->modifiers & num_lock_mask)
|
||||
level = 1;
|
||||
eek_element_set_level (EEK_ELEMENT(self), level);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -309,8 +311,6 @@ eek_section_real_key_released (EekSection *self, EekKey *key)
|
||||
EekKeyboard *keyboard;
|
||||
EekModifierBehavior behavior;
|
||||
EekModifierType modifier;
|
||||
EekModifierType num_lock_mask;
|
||||
gint level = -1;
|
||||
|
||||
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
|
||||
if (!symbol)
|
||||
@ -319,15 +319,18 @@ eek_section_real_key_released (EekSection *self, EekKey *key)
|
||||
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
|
||||
behavior = eek_keyboard_get_modifier_behavior (keyboard);
|
||||
modifier = eek_symbol_get_modifier_mask (symbol);
|
||||
if (modifier != 0) {
|
||||
if (behavior == EEK_MODIFIER_BEHAVIOR_NONE)
|
||||
priv->modifiers &= ~modifier;
|
||||
switch (behavior) {
|
||||
case EEK_MODIFIER_BEHAVIOR_NONE:
|
||||
priv->modifiers &= ~modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LOCK:
|
||||
priv->modifiers ^= modifier;
|
||||
break;
|
||||
case EEK_MODIFIER_BEHAVIOR_LATCH:
|
||||
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
|
||||
break;
|
||||
}
|
||||
|
||||
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
|
||||
if (priv->modifiers & num_lock_mask)
|
||||
level = 1;
|
||||
eek_element_set_level (EEK_ELEMENT(self), level);
|
||||
set_level_from_modifiers (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
288
eek/eek-theme-context.c
Normal file
288
eek/eek-theme-context.c
Normal file
@ -0,0 +1,288 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
|
||||
/*
|
||||
* eek-theme-context.c: holds global information about a tree of styled objects
|
||||
*
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2009 Florian Müllner
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-theme.h"
|
||||
#include "eek-theme-context.h"
|
||||
|
||||
struct _EekThemeContext {
|
||||
GObject parent;
|
||||
|
||||
double resolution;
|
||||
PangoFontDescription *font;
|
||||
EekThemeNode *root_node;
|
||||
EekTheme *theme;
|
||||
};
|
||||
|
||||
struct _EekThemeContextClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
#define DEFAULT_RESOLUTION 96.
|
||||
#define DEFAULT_FONT "sans-serif 10"
|
||||
|
||||
enum
|
||||
{
|
||||
CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
eek_theme_context_finalize (GObject *object)
|
||||
{
|
||||
EekThemeContext *context = EEK_THEME_CONTEXT (object);
|
||||
|
||||
if (context->root_node)
|
||||
g_object_unref (context->root_node);
|
||||
if (context->theme)
|
||||
g_object_unref (context->theme);
|
||||
|
||||
pango_font_description_free (context->font);
|
||||
|
||||
G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_theme_context_class_init (EekThemeContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = eek_theme_context_finalize;
|
||||
|
||||
signals[CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, /* no default handler slot */
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_theme_context_init (EekThemeContext *context)
|
||||
{
|
||||
context->resolution = DEFAULT_RESOLUTION;
|
||||
context->font = pango_font_description_from_string (DEFAULT_FONT);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_new:
|
||||
*
|
||||
* Create a new theme context.
|
||||
*/
|
||||
EekThemeContext *
|
||||
eek_theme_context_new (void)
|
||||
{
|
||||
EekThemeContext *context;
|
||||
|
||||
context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static void
|
||||
eek_theme_context_changed (EekThemeContext *context)
|
||||
{
|
||||
EekThemeNode *old_root = context->root_node;
|
||||
context->root_node = NULL;
|
||||
|
||||
g_signal_emit (context, signals[CHANGED], 0);
|
||||
|
||||
if (old_root)
|
||||
g_object_unref (old_root);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_set_theme:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Sets the default set of theme stylesheets for the context. This theme will
|
||||
* be used for the root node and for nodes descending from it, unless some other
|
||||
* style is explicitely specified.
|
||||
*/
|
||||
void
|
||||
eek_theme_context_set_theme (EekThemeContext *context,
|
||||
EekTheme *theme)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
|
||||
g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
|
||||
|
||||
if (context->theme != theme)
|
||||
{
|
||||
if (context->theme)
|
||||
g_object_unref (context->theme);
|
||||
|
||||
context->theme = theme;
|
||||
|
||||
if (context->theme)
|
||||
g_object_ref (context->theme);
|
||||
|
||||
eek_theme_context_changed (context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_get_theme:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Gets the default theme for the context. See eek_theme_context_set_theme()
|
||||
*
|
||||
* Return value: (transfer none): the default theme for the context
|
||||
*/
|
||||
EekTheme *
|
||||
eek_theme_context_get_theme (EekThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
|
||||
|
||||
return context->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_set_resolution:
|
||||
* @context: a #EekThemeContext
|
||||
* @resolution: resolution of the context (number of pixels in an "inch")
|
||||
*
|
||||
* Sets the resolution of the theme context. This is the scale factor
|
||||
* used to convert between points and the length units pt, in, and cm.
|
||||
* This does not necessarily need to correspond to the actual number
|
||||
* resolution of the device. A value of 72. means that points and
|
||||
* pixels are identical. The default value is 96.
|
||||
*/
|
||||
void
|
||||
eek_theme_context_set_resolution (EekThemeContext *context,
|
||||
double resolution)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
|
||||
|
||||
if (resolution == context->resolution)
|
||||
return;
|
||||
|
||||
context->resolution = resolution;
|
||||
eek_theme_context_changed (context);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_set_default_resolution:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Sets the resolution of the theme context to the default value of 96.
|
||||
* See eek_theme_context_set_resolution().
|
||||
*/
|
||||
void
|
||||
eek_theme_context_set_default_resolution (EekThemeContext *context)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
|
||||
|
||||
if (context->resolution == DEFAULT_RESOLUTION)
|
||||
return;
|
||||
|
||||
context->resolution = DEFAULT_RESOLUTION;
|
||||
eek_theme_context_changed (context);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_get_resolution:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Gets the current resolution of the theme context.
|
||||
* See eek_theme_context_set_resolution().
|
||||
*
|
||||
* Return value: the resolution (in dots-per-"inch")
|
||||
*/
|
||||
double
|
||||
eek_theme_context_get_resolution (EekThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
|
||||
|
||||
return context->resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_set_font:
|
||||
* @context: a #EekThemeContext
|
||||
* @font: the default font for theme context
|
||||
*
|
||||
* Sets the default font for the theme context. This is the font that
|
||||
* is inherited by the root node of the tree of theme nodes. If the
|
||||
* font is not overriden, then this font will be used. If the font is
|
||||
* partially modified (for example, with 'font-size: 110%', then that
|
||||
* modification is based on this font.
|
||||
*/
|
||||
void
|
||||
eek_theme_context_set_font (EekThemeContext *context,
|
||||
const PangoFontDescription *font)
|
||||
{
|
||||
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
|
||||
g_return_if_fail (font != NULL);
|
||||
|
||||
if (context->font == font ||
|
||||
pango_font_description_equal (context->font, font))
|
||||
return;
|
||||
|
||||
pango_font_description_free (context->font);
|
||||
context->font = pango_font_description_copy (font);
|
||||
eek_theme_context_changed (context);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_get_font:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Gets the default font for the theme context. See eek_theme_context_set_font().
|
||||
*
|
||||
* Return value: the default font for the theme context.
|
||||
*/
|
||||
const PangoFontDescription *
|
||||
eek_theme_context_get_font (EekThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
|
||||
|
||||
return context->font;
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_theme_context_get_root_node:
|
||||
* @context: a #EekThemeContext
|
||||
*
|
||||
* Gets the root node of the tree of theme style nodes that associated with this
|
||||
* context. For the node tree associated with a stage, this node represents
|
||||
* styles applied to the stage itself.
|
||||
*
|
||||
* Return value: (transfer none): the root node of the context's style tree
|
||||
*/
|
||||
EekThemeNode *
|
||||
eek_theme_context_get_root_node (EekThemeContext *context)
|
||||
{
|
||||
if (context->root_node == NULL)
|
||||
context->root_node = eek_theme_node_new (context, NULL, context->theme,
|
||||
G_TYPE_NONE, NULL, NULL, NULL, NULL);
|
||||
|
||||
return context->root_node;
|
||||
}
|
||||
78
eek/eek-theme-context.h
Normal file
78
eek/eek-theme-context.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* eek-theme-context.c: holds global information about a tree of styled objects
|
||||
*
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2009 Florian Müllner
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __EEK_THEME_CONTEXT_H__
|
||||
#define __EEK_THEME_CONTEXT_H__
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include "eek-theme-node.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:EekThemeContext
|
||||
* @short_description: holds global information about a tree of styled objects
|
||||
*
|
||||
* #EekThemeContext is responsible for managing information global to
|
||||
* a tree of styled objects, such as the set of stylesheets or the
|
||||
* default font.
|
||||
*/
|
||||
|
||||
typedef struct _EekThemeContextClass EekThemeContextClass;
|
||||
|
||||
#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
|
||||
#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
|
||||
#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
|
||||
#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
|
||||
#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
|
||||
#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
|
||||
|
||||
GType eek_theme_context_get_type
|
||||
(void) G_GNUC_CONST;
|
||||
|
||||
EekThemeContext *eek_theme_context_new
|
||||
(void);
|
||||
|
||||
void eek_theme_context_set_theme
|
||||
(EekThemeContext *context,
|
||||
EekTheme *theme);
|
||||
EekTheme * eek_theme_context_get_theme
|
||||
(EekThemeContext *context);
|
||||
|
||||
void eek_theme_context_set_resolution
|
||||
(EekThemeContext *context,
|
||||
gdouble resolution);
|
||||
void eek_theme_context_set_default_resolution
|
||||
(EekThemeContext *context);
|
||||
double eek_theme_context_get_resolution
|
||||
(EekThemeContext *context);
|
||||
void eek_theme_context_set_font
|
||||
(EekThemeContext *context,
|
||||
const PangoFontDescription *font);
|
||||
const PangoFontDescription *eek_theme_context_get_font
|
||||
(EekThemeContext *context);
|
||||
|
||||
EekThemeNode * eek_theme_context_get_root_node
|
||||
(EekThemeContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EEK_THEME_CONTEXT_H__ */
|
||||
1869
eek/eek-theme-node.c
Normal file
1869
eek/eek-theme-node.c
Normal file
File diff suppressed because it is too large
Load Diff
141
eek/eek-theme-node.h
Normal file
141
eek/eek-theme-node.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
#ifndef __EEK_THEME_NODE_H__
|
||||
#define __EEK_THEME_NODE_H__
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include "eek-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:EekThemeNode
|
||||
* @short_description: style information for one node in a tree of
|
||||
* themed objects
|
||||
*
|
||||
* A #EekThemeNode represents the CSS style information (the set of
|
||||
* CSS properties) for one node in a tree of themed objects. In
|
||||
* typical usage, it represents the style information for a single
|
||||
* #EekElement. A #EekThemeNode is immutable: attributes such as the
|
||||
* CSS classes for the node are passed in at construction. If the
|
||||
* attributes of the node or any parent node change, the node should
|
||||
* be discarded and a new node created. #EekThemeNode has generic
|
||||
* accessors to look up properties by name and specific accessors for
|
||||
* standard CSS properties that add caching and handling of various
|
||||
* details of the CSS specification. #EekThemeNode also has
|
||||
* convenience functions to help in implementing a #EekElement with
|
||||
* borders and padding.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EEK_SIDE_TOP,
|
||||
EEK_SIDE_RIGHT,
|
||||
EEK_SIDE_BOTTOM,
|
||||
EEK_SIDE_LEFT
|
||||
} EekSide;
|
||||
|
||||
typedef enum {
|
||||
EEK_CORNER_TOPLEFT,
|
||||
EEK_CORNER_TOPRIGHT,
|
||||
EEK_CORNER_BOTTOMRIGHT,
|
||||
EEK_CORNER_BOTTOMLEFT
|
||||
} EekCorner;
|
||||
|
||||
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
|
||||
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
|
||||
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
|
||||
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
|
||||
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
|
||||
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
|
||||
|
||||
typedef struct _EekThemeNodeClass EekThemeNodeClass;
|
||||
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
|
||||
|
||||
GType eek_theme_node_get_type
|
||||
(void) G_GNUC_CONST;
|
||||
|
||||
EekThemeNode *eek_theme_node_new (EekThemeContext *context,
|
||||
EekThemeNode *parent_node,
|
||||
/* can be null */ EekTheme *theme,
|
||||
/* can be null */ GType element_type,
|
||||
const char *element_id,
|
||||
const char *element_class,
|
||||
const char *pseudo_class,
|
||||
const char *inline_style);
|
||||
|
||||
EekThemeNode *eek_theme_node_get_parent
|
||||
(EekThemeNode *node);
|
||||
|
||||
EekTheme *eek_theme_node_get_theme
|
||||
(EekThemeNode *node);
|
||||
|
||||
GType eek_theme_node_get_element_type
|
||||
(EekThemeNode *node);
|
||||
const char *eek_theme_node_get_element_id
|
||||
(EekThemeNode *node);
|
||||
const char *eek_theme_node_get_element_class
|
||||
(EekThemeNode *node);
|
||||
const char *eek_theme_node_get_pseudo_class
|
||||
(EekThemeNode *node);
|
||||
|
||||
/* Generic getters ... these are not cached so are less efficient. The other
|
||||
* reason for adding the more specific version is that we can handle the
|
||||
* details of the actual CSS rules, which can be complicated, especially
|
||||
* for fonts
|
||||
*/
|
||||
void eek_theme_node_get_color
|
||||
(EekThemeNode *node,
|
||||
const char *property_name,
|
||||
EekColor *color);
|
||||
|
||||
/* Specific getters for particular properties: cached
|
||||
*/
|
||||
void eek_theme_node_get_background_color
|
||||
(EekThemeNode *node,
|
||||
EekColor *color);
|
||||
void eek_theme_node_get_foreground_color
|
||||
(EekThemeNode *node,
|
||||
EekColor *color);
|
||||
void eek_theme_node_get_background_gradient
|
||||
(EekThemeNode *node,
|
||||
EekGradientType *type,
|
||||
EekColor *start,
|
||||
EekColor *end);
|
||||
int eek_theme_node_get_border_width
|
||||
(EekThemeNode *node,
|
||||
EekSide side);
|
||||
int eek_theme_node_get_border_radius
|
||||
(EekThemeNode *node,
|
||||
EekCorner corner);
|
||||
void eek_theme_node_get_border_color
|
||||
(EekThemeNode *node,
|
||||
EekSide side,
|
||||
EekColor *color);
|
||||
|
||||
/* Font rule processing is pretty complicated, so we just hardcode it
|
||||
* under the standard font/font-family/font-size/etc names. This means
|
||||
* you can't have multiple separate styled fonts for a single item,
|
||||
* but that should be OK.
|
||||
*/
|
||||
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EEK_THEME_NODE_H__ */
|
||||
22
eek/eek-theme-private.h
Normal file
22
eek/eek-theme-private.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __EEK_THEME_PRIVATE_H__
|
||||
#define __EEK_THEME_PRIVATE_H__
|
||||
|
||||
#include <libcroco/libcroco.h>
|
||||
#include "eek-theme.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GPtrArray *_eek_theme_get_matched_properties (EekTheme *theme,
|
||||
EekThemeNode *node);
|
||||
|
||||
/* Resolve an URL from the stylesheet to a filename */
|
||||
char *_eek_theme_resolve_url (EekTheme *theme,
|
||||
CRStyleSheet *base_stylesheet,
|
||||
const char *url);
|
||||
|
||||
CRDeclaration *_eek_theme_parse_declaration_list (const char *str);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EEK_THEME_PRIVATE_H__ */
|
||||
1133
eek/eek-theme.c
Normal file
1133
eek/eek-theme.c
Normal file
File diff suppressed because it is too large
Load Diff
44
eek/eek-theme.h
Normal file
44
eek/eek-theme.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __EEK_THEME_H__
|
||||
#define __EEK_THEME_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "eek-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:EekTheme
|
||||
* @short_description: a set of stylesheets
|
||||
*
|
||||
* #EekTheme holds a set of stylesheets. (The "cascade" of the name
|
||||
* Cascading Stylesheets.) An #EekTheme can be set to apply to all the
|
||||
* keyboard elements.
|
||||
*/
|
||||
|
||||
typedef struct _EekThemeClass EekThemeClass;
|
||||
|
||||
#define EEK_TYPE_THEME (eek_theme_get_type())
|
||||
#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
|
||||
#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
|
||||
#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
|
||||
#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
|
||||
#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
|
||||
|
||||
GType eek_theme_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekTheme *eek_theme_new (const char *application_stylesheet,
|
||||
const char *theme_stylesheet,
|
||||
const char *default_stylesheet);
|
||||
|
||||
gboolean eek_theme_load_stylesheet (EekTheme *theme,
|
||||
const char *path,
|
||||
GError **error);
|
||||
|
||||
void eek_theme_unload_stylesheet (EekTheme *theme,
|
||||
const char *path);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EEK_THEME_H__ */
|
||||
@ -153,6 +153,7 @@ EekOutline *
|
||||
eek_outline_copy (const EekOutline *outline)
|
||||
{
|
||||
EekOutline *_outline = g_slice_dup (EekOutline, outline);
|
||||
_outline->corner_radius = outline->corner_radius;
|
||||
_outline->num_points = outline->num_points;
|
||||
_outline->points = g_slice_alloc0 (sizeof (EekPoint) * outline->num_points);
|
||||
memcpy (_outline->points, outline->points, sizeof (EekPoint) * outline->num_points);
|
||||
@ -180,13 +181,13 @@ eek_outline_get_type (void)
|
||||
}
|
||||
|
||||
/* EekColor */
|
||||
static EekColor *
|
||||
EekColor *
|
||||
eek_color_copy (const EekColor *color)
|
||||
{
|
||||
return g_slice_dup (EekColor, color);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
eek_color_free (EekColor *color)
|
||||
{
|
||||
g_slice_free (EekColor, color);
|
||||
|
||||
@ -136,6 +136,9 @@ typedef struct _EekSection EekSection;
|
||||
typedef struct _EekKeyboard EekKeyboard;
|
||||
typedef struct _EekSymbol EekSymbol;
|
||||
typedef struct _EekKeysym EekKeysym;
|
||||
typedef struct _EekTheme EekTheme;
|
||||
typedef struct _EekThemeContext EekThemeContext;
|
||||
typedef struct _EekThemeNode EekThemeNode;
|
||||
|
||||
typedef struct _EekSymbolMatrix EekSymbolMatrix;
|
||||
typedef struct _EekPoint EekPoint;
|
||||
@ -246,10 +249,19 @@ struct _EekColor
|
||||
|
||||
GType eek_color_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekColor *eek_color_new (gdouble red,
|
||||
gdouble green,
|
||||
gdouble blue,
|
||||
gdouble alpha);
|
||||
EekColor *eek_color_new (gdouble red,
|
||||
gdouble green,
|
||||
gdouble blue,
|
||||
gdouble alpha);
|
||||
EekColor *eek_color_copy (const EekColor *color);
|
||||
void eek_color_free (EekColor *color);
|
||||
|
||||
typedef enum {
|
||||
EEK_GRADIENT_NONE,
|
||||
EEK_GRADIENT_VERTICAL,
|
||||
EEK_GRADIENT_HORIZONTAL,
|
||||
EEK_GRADIENT_RADIAL
|
||||
} EekGradientType;
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_TYPES_H */
|
||||
|
||||
@ -27,16 +27,16 @@
|
||||
* elements using XKB.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBgeom.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-xkb-layout.h"
|
||||
#include "eek-keyboard.h"
|
||||
#include "eek-section.h"
|
||||
@ -176,6 +176,7 @@ create_key (EekXkbLayout *layout,
|
||||
}
|
||||
}
|
||||
oref = eek_keyboard_add_outline (keyboard, outline);
|
||||
eek_outline_free (outline);
|
||||
g_hash_table_insert (priv->shape_oref_hash, xkbshape, (gpointer)oref);
|
||||
}
|
||||
|
||||
@ -324,9 +325,13 @@ eek_xkb_layout_real_create_keyboard (EekLayout *self,
|
||||
bounds.height = initial_height;
|
||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
|
||||
/* resolve modifiers dynamically assigned at run time */
|
||||
eek_keyboard_set_num_lock_mask (keyboard,
|
||||
XkbKeysymToModifiers (priv->display,
|
||||
XK_Num_Lock));
|
||||
eek_keyboard_set_alt_gr_mask (keyboard,
|
||||
XkbKeysymToModifiers (priv->display,
|
||||
XK_ISO_Level3_Shift));
|
||||
|
||||
if (priv->shape_oref_hash)
|
||||
g_hash_table_destroy (priv->shape_oref_hash);
|
||||
|
||||
@ -26,14 +26,14 @@
|
||||
* to use Libxklavier configuration.
|
||||
*/
|
||||
|
||||
#include <libxklavier/xklavier.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <libxklavier/xklavier.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eek-xkl-layout.h"
|
||||
|
||||
#define noKBDRAW_DEBUG
|
||||
|
||||
@ -62,6 +62,7 @@ struct _ParseCallbackData {
|
||||
EekKey *key;
|
||||
gint num_columns;
|
||||
EekOrientation orientation;
|
||||
gdouble corner_radius;
|
||||
GSList *points;
|
||||
GSList *symbols;
|
||||
gchar *label;
|
||||
@ -70,6 +71,7 @@ struct _ParseCallbackData {
|
||||
gint groups, levels;
|
||||
EekOutline outline;
|
||||
gchar *oref;
|
||||
|
||||
GHashTable *key_oref_hash;
|
||||
GHashTable *oref_outline_hash;
|
||||
};
|
||||
@ -97,7 +99,8 @@ static const gchar *valid_path_list[] = {
|
||||
"icon/symbols/key/section/keyboard",
|
||||
"invalid/symbols/key/section/keyboard",
|
||||
"index/key/section/keyboard",
|
||||
"point/outline/keyboard"
|
||||
"point/outline/keyboard",
|
||||
"corner-radius/outline/keyboard",
|
||||
};
|
||||
|
||||
static gchar *
|
||||
@ -298,7 +301,10 @@ end_element_callback (GMarkupParseContext *pcontext,
|
||||
|
||||
if (g_strcmp0 (element_name, "outline") == 0) {
|
||||
EekOutline *outline = g_slice_new (EekOutline);
|
||||
|
||||
|
||||
outline->corner_radius = data->corner_radius;
|
||||
data->corner_radius = 0.0;
|
||||
|
||||
outline->num_points = g_slist_length (data->points);
|
||||
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
|
||||
outline->num_points);
|
||||
@ -318,6 +324,11 @@ end_element_callback (GMarkupParseContext *pcontext,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (element_name, "corner-radius") == 0) {
|
||||
data->corner_radius = g_strtod (text, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (element_name, "point") == 0) {
|
||||
EekPoint *point;
|
||||
|
||||
|
||||
@ -21,14 +21,14 @@
|
||||
* @short_description: #EekKeyboard to XML conversion utilities
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include "eek-section.h"
|
||||
#include "eek-key.h"
|
||||
#include "eek-xml.h"
|
||||
@ -273,6 +273,9 @@ eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
|
||||
outline = eek_keyboard_get_outline (keyboard, oref);
|
||||
g_string_append_indent (output, indent + 1);
|
||||
g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
|
||||
g_string_append_indent (output, indent + 2);
|
||||
g_string_markup_printf (output, "<corner-radius>%lf</corner-radius>\n",
|
||||
outline->corner_radius);
|
||||
for (j = 0; j < outline->num_points; j++) {
|
||||
g_string_append_indent (output, indent + 2);
|
||||
g_string_markup_printf (output, "<point>%lf,%lf</point>\n",
|
||||
|
||||
@ -28,5 +28,6 @@
|
||||
#include "eek-keysym.h"
|
||||
#include "eek-xml.h"
|
||||
#include "eek-serializable.h"
|
||||
#include "eek-theme.h"
|
||||
|
||||
#endif /* EEK_H */
|
||||
|
||||
@ -37,6 +37,7 @@ enum {
|
||||
DISABLED,
|
||||
KEY_PRESSED,
|
||||
KEY_RELEASED,
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -59,6 +60,7 @@ struct _EekboardContextPrivate
|
||||
GHashTable *keyboard_hash;
|
||||
gboolean keyboard_visible;
|
||||
gboolean enabled;
|
||||
gboolean fullscreen;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -146,6 +148,12 @@ eekboard_context_real_key_released (EekboardContext *self,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_real_destroyed (EekboardContext *self)
|
||||
{
|
||||
// g_debug ("eekboard_context_real_destroyed");
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_context_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -195,6 +203,7 @@ eekboard_context_class_init (EekboardContextClass *klass)
|
||||
klass->disabled = eekboard_context_real_disabled;
|
||||
klass->key_pressed = eekboard_context_real_key_pressed;
|
||||
klass->key_released = eekboard_context_real_key_released;
|
||||
klass->destroyed = eekboard_context_real_destroyed;
|
||||
|
||||
proxy_class->g_signal = eekboard_context_real_g_signal;
|
||||
|
||||
@ -288,6 +297,24 @@ eekboard_context_class_init (EekboardContextClass *klass)
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_UINT);
|
||||
|
||||
/**
|
||||
* EekboardContext::destroyed:
|
||||
* @context: an #EekboardContext
|
||||
*
|
||||
* The ::destroyed signal is emitted each time the name of remote
|
||||
* end is vanished.
|
||||
*/
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardContextClass, destroyed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -306,6 +333,15 @@ eekboard_context_init (EekboardContext *self)
|
||||
(GDestroyNotify)g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
context_name_vanished_callback (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardContext *context = user_data;
|
||||
g_signal_emit_by_name (context, "destroyed", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_new:
|
||||
* @connection: a #GDBusConnection
|
||||
@ -337,8 +373,27 @@ eekboard_context_new (GDBusConnection *connection,
|
||||
"g-interface-name", "com.redhat.Eekboard.Context",
|
||||
"g-object-path", object_path,
|
||||
NULL);
|
||||
if (initable != NULL)
|
||||
return EEKBOARD_CONTEXT (initable);
|
||||
if (initable != NULL) {
|
||||
EekboardContext *context = EEKBOARD_CONTEXT (initable);
|
||||
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(context));
|
||||
|
||||
if (name_owner == NULL) {
|
||||
g_object_unref (context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the vanished callback is called when the server is disconnected */
|
||||
g_bus_watch_name_on_connection (connection,
|
||||
name_owner,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
NULL,
|
||||
context_name_vanished_callback,
|
||||
context,
|
||||
NULL);
|
||||
g_free (name_owner);
|
||||
|
||||
return context;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -380,6 +435,8 @@ eekboard_context_add_keyboard (EekboardContext *context,
|
||||
priv = EEKBOARD_CONTEXT_GET_PRIVATE (context);
|
||||
|
||||
variant = eek_serializable_serialize (EEK_SERIALIZABLE(keyboard));
|
||||
if (g_variant_is_floating (variant))
|
||||
g_variant_ref_sink (variant);
|
||||
|
||||
error = NULL;
|
||||
result = g_dbus_proxy_call_sync (G_DBUS_PROXY(context),
|
||||
@ -502,15 +559,17 @@ eekboard_context_set_group (EekboardContext *context,
|
||||
|
||||
g_return_if_fail (priv->keyboard);
|
||||
|
||||
eek_element_set_group (EEK_ELEMENT(priv->keyboard), group);
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetGroup",
|
||||
g_variant_new ("(i)", group),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
if (eek_element_get_group (EEK_ELEMENT(priv->keyboard)) != group) {
|
||||
eek_element_set_group (EEK_ELEMENT(priv->keyboard), group);
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetGroup",
|
||||
g_variant_new ("(i)", group),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -688,3 +747,33 @@ eekboard_context_is_enabled (EekboardContext *context)
|
||||
priv = EEKBOARD_CONTEXT_GET_PRIVATE (context);
|
||||
return priv->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_context_set_fullscreen:
|
||||
* @context: an #EekboardContext
|
||||
* @fullscreen: a flag to indicate fullscreen mode
|
||||
* @cancellable: a #GCancellable
|
||||
*
|
||||
* Set the fullscreen mode of @context.
|
||||
*/
|
||||
void
|
||||
eekboard_context_set_fullscreen (EekboardContext *context,
|
||||
gboolean fullscreen,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
EekboardContextPrivate *priv;
|
||||
|
||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
||||
|
||||
priv = EEKBOARD_CONTEXT_GET_PRIVATE (context);
|
||||
if (priv->fullscreen != fullscreen) {
|
||||
g_dbus_proxy_call (G_DBUS_PROXY(context),
|
||||
"SetFullscreen",
|
||||
g_variant_new ("(b)", fullscreen),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
cancellable,
|
||||
context_async_ready_callback,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,45 +66,48 @@ struct _EekboardContextClass {
|
||||
guint keycode);
|
||||
void (*key_released) (EekboardContext *self,
|
||||
guint keycode);
|
||||
void (*destroyed) (EekboardContext *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
gpointer pdummy[23];
|
||||
};
|
||||
|
||||
GType eekboard_context_get_type (void) G_GNUC_CONST;
|
||||
GType eekboard_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
EekboardContext *eekboard_context_new (GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
GCancellable *cancellable);
|
||||
guint eekboard_context_add_keyboard (EekboardContext *context,
|
||||
EekKeyboard *keyboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_remove_keyboard
|
||||
(EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_show_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_hide_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_group (EekboardContext *context,
|
||||
gint group,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_press_key (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_release_key (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
EekboardContext *eekboard_context_new (GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
GCancellable *cancellable);
|
||||
guint eekboard_context_add_keyboard (EekboardContext *context,
|
||||
EekKeyboard *keyboard,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_remove_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_keyboard (EekboardContext *context,
|
||||
guint keyboard_id,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_show_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_hide_keyboard (EekboardContext *context,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_set_group (EekboardContext *context,
|
||||
gint group,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_press_key (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
void eekboard_context_release_key (EekboardContext *context,
|
||||
guint keycode,
|
||||
GCancellable *cancellable);
|
||||
gboolean eekboard_context_is_keyboard_visible
|
||||
(EekboardContext *context);
|
||||
void eekboard_context_set_enabled (EekboardContext *context,
|
||||
gboolean enabled);
|
||||
gboolean eekboard_context_is_enabled (EekboardContext *context);
|
||||
(EekboardContext *context);
|
||||
void eekboard_context_set_enabled (EekboardContext *context,
|
||||
gboolean enabled);
|
||||
gboolean eekboard_context_is_enabled (EekboardContext *context);
|
||||
void eekboard_context_set_fullscreen (EekboardContext *context,
|
||||
gboolean fullscreen,
|
||||
GCancellable *cancellable);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEKBOARD_CONTEXT_H */
|
||||
|
||||
@ -29,6 +29,13 @@
|
||||
|
||||
#include "eekboard/eekboard-eekboard.h"
|
||||
|
||||
enum {
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE (EekboardEekboard, eekboard_eekboard, G_TYPE_DBUS_PROXY);
|
||||
|
||||
#define EEKBOARD_EEKBOARD_GET_PRIVATE(obj) \
|
||||
@ -39,6 +46,15 @@ struct _EekboardEekboardPrivate
|
||||
GHashTable *context_hash;
|
||||
};
|
||||
|
||||
static void
|
||||
eekboard_eekboard_real_destroyed (EekboardEekboard *self)
|
||||
{
|
||||
EekboardEekboardPrivate *priv = EEKBOARD_EEKBOARD_GET_PRIVATE(self);
|
||||
|
||||
// g_debug ("eekboard_eekboard_real_destroyed");
|
||||
g_hash_table_remove_all (priv->context_hash);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_eekboard_dispose (GObject *object)
|
||||
{
|
||||
@ -60,7 +76,27 @@ eekboard_eekboard_class_init (EekboardEekboardClass *klass)
|
||||
g_type_class_add_private (gobject_class,
|
||||
sizeof (EekboardEekboardPrivate));
|
||||
|
||||
klass->destroyed = eekboard_eekboard_real_destroyed;
|
||||
|
||||
gobject_class->dispose = eekboard_eekboard_dispose;
|
||||
|
||||
/**
|
||||
* EekboardEekboard::destroyed:
|
||||
* @eekboard: an #EekboardEekboard
|
||||
*
|
||||
* The ::destroyed signal is emitted each time the name of remote
|
||||
* end is vanished.
|
||||
*/
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET(EekboardEekboardClass, destroyed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -76,6 +112,15 @@ eekboard_eekboard_init (EekboardEekboard *self)
|
||||
(GDestroyNotify)g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
eekboard_name_vanished_callback (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardEekboard *eekboard = user_data;
|
||||
g_signal_emit_by_name (eekboard, "destroyed", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_eekboard_new:
|
||||
* @connection: a #GDBusConnection
|
||||
@ -102,11 +147,40 @@ eekboard_eekboard_new (GDBusConnection *connection,
|
||||
"g-interface-name", "com.redhat.Eekboard.Server",
|
||||
"g-object-path", "/com/redhat/Eekboard/Server",
|
||||
NULL);
|
||||
if (initable != NULL)
|
||||
return EEKBOARD_EEKBOARD (initable);
|
||||
if (initable != NULL) {
|
||||
EekboardEekboard *eekboard = EEKBOARD_EEKBOARD (initable);
|
||||
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(eekboard));
|
||||
if (name_owner == NULL) {
|
||||
g_object_unref (eekboard);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the vanished callback is called when the server is disconnected */
|
||||
g_bus_watch_name_on_connection (connection,
|
||||
name_owner,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
NULL,
|
||||
eekboard_name_vanished_callback,
|
||||
eekboard,
|
||||
NULL);
|
||||
g_free (name_owner);
|
||||
|
||||
return eekboard;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_context_destroyed (EekboardContext *context,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekboardEekboard *eekboard = user_data;
|
||||
EekboardEekboardPrivate *priv = EEKBOARD_EEKBOARD_GET_PRIVATE(eekboard);
|
||||
|
||||
g_hash_table_remove (priv->context_hash,
|
||||
g_dbus_proxy_get_object_path (G_DBUS_PROXY(context)));
|
||||
}
|
||||
|
||||
/**
|
||||
* eekboard_eekboard_create_context:
|
||||
* @eekboard: an #EekboardEekboard
|
||||
@ -153,6 +227,8 @@ eekboard_eekboard_create_context (EekboardEekboard *eekboard,
|
||||
g_hash_table_insert (priv->context_hash,
|
||||
g_strdup (object_path),
|
||||
g_object_ref (context));
|
||||
g_signal_connect (context, "destroyed",
|
||||
G_CALLBACK(on_context_destroyed), eekboard);
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
@ -45,9 +45,12 @@ struct _EekboardEekboardClass {
|
||||
/*< private >*/
|
||||
GDBusProxyClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* destroyed) (EekboardEekboard *self);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[24];
|
||||
gpointer pdummy[23];
|
||||
};
|
||||
|
||||
GType eekboard_eekboard_get_type (void) G_GNUC_CONST;
|
||||
|
||||
@ -3,4 +3,5 @@ eek/eek-container.c
|
||||
eek/eek-key.c
|
||||
eek/eek-keyboard.c
|
||||
eek/eek-section.c
|
||||
eekboard/eekboard-eekboard.c
|
||||
eekboard/eekboard-context.c
|
||||
|
||||
@ -64,7 +64,8 @@ eekboard_desktop_client_SOURCES = desktop-client.c desktop-client-main.c
|
||||
eekboard_server_CFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
$(GIO2_CFLAGS) \
|
||||
$(GTK_CFLAGS)
|
||||
$(GTK_CFLAGS) \
|
||||
-DTHEMEDIR=\"$(pkgdatadir)/themes\"
|
||||
|
||||
eekboard_server_LDADD = \
|
||||
$(top_builddir)/eekboard/libeekboard.la \
|
||||
@ -73,14 +74,14 @@ eekboard_server_LDADD = \
|
||||
$(GIO2_LIBS) \
|
||||
$(GTK_LIBS)
|
||||
|
||||
eekboard_server_headers = server-server.h server-context.h
|
||||
eekboard_server_SOURCES = server-server.c server-context.c server-main.c
|
||||
|
||||
if ENABLE_CLUTTER
|
||||
eekboard_server_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
|
||||
eekboard_server_LDADD += $(CLUTTER_LIBS) $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
|
||||
endif
|
||||
|
||||
eekboard_server_headers = server-server.h server-context.h
|
||||
eekboard_server_SOURCES = server-server.c server-context.c server-main.c
|
||||
|
||||
eekboard_client_CFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
$(GIO2_CFLAGS)
|
||||
@ -107,6 +108,11 @@ eekboard_xml_LDADD = \
|
||||
$(GTK_LIBS) \
|
||||
$(LIBXKLAVIER_LIBS)
|
||||
|
||||
if ENABLE_CLUTTER
|
||||
eekboard_xml_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
|
||||
eekboard_xml_LDADD += $(CLUTTER_LIBS) $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
|
||||
endif
|
||||
|
||||
eekboard_xml_SOURCES = xml-main.c
|
||||
|
||||
libxklutil_la_headers = xklutil.h
|
||||
|
||||
@ -40,6 +40,8 @@ static gchar *opt_model = NULL;
|
||||
static gchar *opt_layouts = NULL;
|
||||
static gchar *opt_options = NULL;
|
||||
|
||||
static gboolean opt_fullscreen = FALSE;
|
||||
|
||||
static const GOptionEntry options[] = {
|
||||
{"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
|
||||
N_("Connect to the system bus")},
|
||||
@ -59,6 +61,8 @@ static const GOptionEntry options[] = {
|
||||
N_("Specify layouts")},
|
||||
{"options", '\0', 0, G_OPTION_ARG_STRING, &opt_options,
|
||||
N_("Specify options")},
|
||||
{"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
|
||||
N_("Create window in fullscreen mode")},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@ -77,10 +81,29 @@ on_notify_keyboard_visible (GObject *object,
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_context_destroyed (EekboardContext *context,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroyed (EekboardEekboard *eekboard,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
EekboardDesktopClient *client;
|
||||
EekboardEekboard *eekboard;
|
||||
EekboardContext *context;
|
||||
GBusType bus_type;
|
||||
GDBusConnection *connection;
|
||||
@ -136,6 +159,10 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
client = eekboard_desktop_client_new (connection);
|
||||
if (client == NULL) {
|
||||
g_printerr ("Can't create a client\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gconfc = gconf_client_get_default ();
|
||||
|
||||
@ -196,9 +223,21 @@ main (int argc, char **argv)
|
||||
g_object_get (client, "context", &context, NULL);
|
||||
g_signal_connect (context, "notify::keyboard-visible",
|
||||
G_CALLBACK(on_notify_keyboard_visible), loop);
|
||||
g_signal_connect (context, "destroyed",
|
||||
G_CALLBACK(on_context_destroyed), loop);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
if (opt_fullscreen) {
|
||||
g_object_get (client, "context", &context, NULL);
|
||||
eekboard_context_set_fullscreen (context, TRUE, NULL);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
g_object_get (client, "eekboard", &eekboard, NULL);
|
||||
g_signal_connect (eekboard, "destroyed",
|
||||
G_CALLBACK(on_destroyed), loop);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CONNECTION,
|
||||
PROP_EEKBOARD,
|
||||
PROP_CONTEXT,
|
||||
PROP_LAST
|
||||
};
|
||||
@ -67,6 +68,7 @@ struct _EekboardDesktopClient {
|
||||
gulong key_released_handler;
|
||||
|
||||
#ifdef HAVE_CSPI
|
||||
Accessible *acc;
|
||||
AccessibleEventListener *focus_listener;
|
||||
AccessibleEventListener *keystroke_listener;
|
||||
#endif /* HAVE_CSPI */
|
||||
@ -124,15 +126,19 @@ eekboard_desktop_client_set_property (GObject *object,
|
||||
connection = g_value_get_object (value);
|
||||
|
||||
client->eekboard = eekboard_eekboard_new (connection, NULL);
|
||||
g_assert (client->eekboard);
|
||||
|
||||
client->context =
|
||||
eekboard_eekboard_create_context (client->eekboard,
|
||||
"eekboard-desktop-client",
|
||||
NULL);
|
||||
g_assert (client->context);
|
||||
|
||||
eekboard_eekboard_push_context (client->eekboard, client->context, NULL);
|
||||
if (client->eekboard != NULL) {
|
||||
client->context =
|
||||
eekboard_eekboard_create_context (client->eekboard,
|
||||
"eekboard-desktop-client",
|
||||
NULL);
|
||||
if (client->context == NULL) {
|
||||
g_object_unref (client->eekboard);
|
||||
client->eekboard = NULL;
|
||||
} else
|
||||
eekboard_eekboard_push_context (client->eekboard,
|
||||
client->context,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_object_set_property (object,
|
||||
@ -151,6 +157,9 @@ eekboard_desktop_client_get_property (GObject *object,
|
||||
EekboardDesktopClient *client = EEKBOARD_DESKTOP_CLIENT(object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_EEKBOARD:
|
||||
g_value_set_object (value, client->eekboard);
|
||||
break;
|
||||
case PROP_CONTEXT:
|
||||
g_value_set_object (value, client->context);
|
||||
break;
|
||||
@ -230,6 +239,15 @@ eekboard_desktop_client_class_init (EekboardDesktopClientClass *klass)
|
||||
PROP_CONNECTION,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_object ("eekboard",
|
||||
"Eekboard",
|
||||
"Eekboard",
|
||||
EEKBOARD_TYPE_EEKBOARD,
|
||||
G_PARAM_READABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_EEKBOARD,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_object ("context",
|
||||
"Context",
|
||||
"Context",
|
||||
@ -416,10 +434,24 @@ focus_listener_cb (const AccessibleEvent *event,
|
||||
case SPI_ROLE_PARAGRAPH:
|
||||
case SPI_ROLE_PASSWORD_TEXT:
|
||||
case SPI_ROLE_TERMINAL:
|
||||
case SPI_ROLE_ENTRY:
|
||||
if (g_strcmp0 (event->type, "focus") == 0 || event->detail1 == 1) {
|
||||
if (strncmp (event->type, "focus", 5) == 0 || event->detail1 == 1) {
|
||||
client->acc = accessible;
|
||||
eekboard_context_show_keyboard (client->context, NULL);
|
||||
} else if (event->detail1 == 0 && accessible == client->acc) {
|
||||
client->acc = NULL;
|
||||
eekboard_context_hide_keyboard (client->context, NULL);
|
||||
}
|
||||
break;
|
||||
case SPI_ROLE_ENTRY:
|
||||
if (strncmp (event->type, "focus", 5) == 0 || event->detail1 == 1) {
|
||||
client->acc = accessible;
|
||||
eekboard_context_show_keyboard (client->context, NULL);
|
||||
} else if (event->detail1 == 0) {
|
||||
client->acc = NULL;
|
||||
eekboard_context_hide_keyboard (client->context, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
@ -460,9 +492,12 @@ keystroke_listener_cb (const AccessibleKeystroke *stroke,
|
||||
EekboardDesktopClient *
|
||||
eekboard_desktop_client_new (GDBusConnection *connection)
|
||||
{
|
||||
return g_object_new (EEKBOARD_TYPE_DESKTOP_CLIENT,
|
||||
"connection", connection,
|
||||
NULL);
|
||||
EekboardDesktopClient *client = g_object_new (EEKBOARD_TYPE_DESKTOP_CLIENT,
|
||||
"connection", connection,
|
||||
NULL);
|
||||
if (client->context)
|
||||
return client;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
@ -554,6 +589,7 @@ set_keyboard (EekboardDesktopClient *client,
|
||||
|
||||
keyboard_name = g_strdup_printf ("keyboard%d", keyboard_serial++);
|
||||
eek_element_set_name (EEK_ELEMENT(client->keyboard), keyboard_name);
|
||||
g_free (keyboard_name);
|
||||
|
||||
keyboard_id = eekboard_context_add_keyboard (client->context,
|
||||
client->keyboard,
|
||||
@ -583,6 +619,23 @@ on_xkl_state_changed (XklEngine *xklengine,
|
||||
}
|
||||
|
||||
#ifdef HAVE_FAKEKEY
|
||||
G_INLINE_FUNC FakeKeyModifier
|
||||
get_fakekey_modifiers (EekModifierType modifiers)
|
||||
{
|
||||
FakeKeyModifier retval = 0;
|
||||
|
||||
if (modifiers & EEK_SHIFT_MASK)
|
||||
retval |= FAKEKEYMOD_SHIFT;
|
||||
if (modifiers & EEK_CONTROL_MASK)
|
||||
retval |= FAKEKEYMOD_CONTROL;
|
||||
if (modifiers & EEK_MOD1_MASK)
|
||||
retval |= FAKEKEYMOD_ALT;
|
||||
if (modifiers & EEK_META_MASK)
|
||||
retval |= FAKEKEYMOD_META;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_pressed (EekKeyboard *keyboard,
|
||||
EekKey *key,
|
||||
@ -595,10 +648,21 @@ on_key_pressed (EekKeyboard *keyboard,
|
||||
|
||||
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
|
||||
if (EEK_IS_KEYSYM(symbol) && !eek_symbol_is_modifier (symbol)) {
|
||||
fakekey_press_keysym (client->fakekey,
|
||||
eek_keysym_get_xkeysym (EEK_KEYSYM(symbol)),
|
||||
0);
|
||||
fakekey_release (client->fakekey);
|
||||
guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
|
||||
guint keycode =
|
||||
XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (client->display), xkeysym);
|
||||
EekModifierType modifiers =
|
||||
eek_keyboard_get_modifiers (client->keyboard);
|
||||
FakeKeyModifier fakekey_modifiers = get_fakekey_modifiers (modifiers);
|
||||
|
||||
fakekey_send_keyevent (client->fakekey,
|
||||
keycode,
|
||||
TRUE,
|
||||
fakekey_modifiers);
|
||||
fakekey_send_keyevent (client->fakekey,
|
||||
keycode,
|
||||
FALSE,
|
||||
fakekey_modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -56,6 +56,9 @@ static const gchar introspection_xml[] =
|
||||
" <method name='SetKeyboard'>"
|
||||
" <arg type='u' name='keyboard_id'/>"
|
||||
" </method>"
|
||||
" <method name='SetFullscreen'>"
|
||||
" <arg type='b' name='fullscreen'/>"
|
||||
" </method>"
|
||||
" <method name='ShowKeyboard'/>"
|
||||
" <method name='HideKeyboard'/>"
|
||||
" <method name='SetGroup'>"
|
||||
@ -94,6 +97,7 @@ struct _ServerContext {
|
||||
|
||||
gboolean enabled;
|
||||
gboolean last_keyboard_visible;
|
||||
gboolean fullscreen;
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *widget;
|
||||
@ -191,14 +195,61 @@ on_realize (GtkWidget *widget,
|
||||
GDK_FUNC_CLOSE);
|
||||
}
|
||||
|
||||
#define DEFAULT_THEME (THEMEDIR "/default.css")
|
||||
|
||||
static void
|
||||
update_widget (ServerContext *context)
|
||||
set_geometry (ServerContext *context)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
GdkWindow *root;
|
||||
gint monitor;
|
||||
GdkRectangle rect;
|
||||
EekBounds bounds;
|
||||
|
||||
screen = gdk_screen_get_default ();
|
||||
root = gtk_widget_get_root_window (context->window);
|
||||
monitor = gdk_screen_get_monitor_at_window (screen, root);
|
||||
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
|
||||
eek_element_get_bounds (EEK_ELEMENT(context->keyboard), &bounds);
|
||||
|
||||
if (context->fullscreen) {
|
||||
gtk_window_set_decorated (GTK_WINDOW(context->window), FALSE);
|
||||
gtk_window_set_resizable (GTK_WINDOW(context->window), FALSE);
|
||||
gtk_widget_set_size_request (context->widget,
|
||||
rect.width,
|
||||
rect.height / 2);
|
||||
gtk_window_move (GTK_WINDOW(context->window),
|
||||
0,
|
||||
rect.height / 2);
|
||||
gtk_window_set_opacity (GTK_WINDOW(context->window), 0.8);
|
||||
} else {
|
||||
#if HAVE_CLUTTER_GTK
|
||||
ClutterActor *stage =
|
||||
gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(context->widget));
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE(stage), TRUE);
|
||||
clutter_stage_set_minimum_size (CLUTTER_STAGE(stage),
|
||||
bounds.width / 3,
|
||||
bounds.height / 3);
|
||||
g_signal_connect (stage,
|
||||
"allocation-changed",
|
||||
G_CALLBACK(on_allocation_changed),
|
||||
actor);
|
||||
#else
|
||||
gtk_widget_set_size_request (context->widget,
|
||||
bounds.width,
|
||||
bounds.height);
|
||||
#endif
|
||||
gtk_window_move (GTK_WINDOW(context->window),
|
||||
MAX(rect.width - 20 - bounds.width, 0),
|
||||
MAX(rect.height - 40 - bounds.height, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_widget (ServerContext *context)
|
||||
{
|
||||
EekBounds bounds;
|
||||
EekTheme *theme;
|
||||
#if HAVE_CLUTTER_GTK
|
||||
ClutterActor *stage, *actor;
|
||||
ClutterColor stage_color = { 0xff, 0xff, 0xff, 0xff };
|
||||
@ -207,26 +258,22 @@ update_widget (ServerContext *context)
|
||||
if (context->widget)
|
||||
gtk_widget_destroy (context->widget);
|
||||
|
||||
theme = eek_theme_new (DEFAULT_THEME, NULL, NULL);
|
||||
eek_element_get_bounds (EEK_ELEMENT(context->keyboard), &bounds);
|
||||
#if HAVE_CLUTTER_GTK
|
||||
context->widget = gtk_clutter_embed_new ();
|
||||
stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(context->widget));
|
||||
actor = eek_clutter_keyboard_new (context->keyboard);
|
||||
if (theme)
|
||||
eek_clutter_keyboard_set_theme (EEK_CLUTTER_KEYBOARD(actor), theme);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage), actor);
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE(stage), TRUE);
|
||||
clutter_stage_set_minimum_size (CLUTTER_STAGE(stage),
|
||||
bounds.width / 3,
|
||||
bounds.height / 3);
|
||||
g_signal_connect (stage,
|
||||
"allocation-changed",
|
||||
G_CALLBACK(on_allocation_changed),
|
||||
actor);
|
||||
#else
|
||||
context->widget = eek_gtk_keyboard_new (context->keyboard);
|
||||
if (theme)
|
||||
eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(context->widget), theme);
|
||||
#endif
|
||||
gtk_widget_set_size_request (context->widget, bounds.width, bounds.height);
|
||||
|
||||
if (!context->window) {
|
||||
context->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
@ -245,13 +292,7 @@ update_widget (ServerContext *context)
|
||||
g_signal_connect (context->window, "realize",
|
||||
G_CALLBACK(on_realize), context);
|
||||
|
||||
screen = gdk_screen_get_default ();
|
||||
root = gtk_widget_get_root_window (context->window);
|
||||
monitor = gdk_screen_get_monitor_at_window (screen, root);
|
||||
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
|
||||
gtk_window_move (GTK_WINDOW(context->window),
|
||||
MAX(rect.width - 20 - bounds.width, 0),
|
||||
MAX(rect.height - 40 - bounds.height, 0));
|
||||
set_geometry (context);
|
||||
}
|
||||
gtk_container_add (GTK_CONTAINER(context->window), context->widget);
|
||||
}
|
||||
@ -329,6 +370,7 @@ server_context_finalize (GObject *object)
|
||||
{
|
||||
ServerContext *context = SERVER_CONTEXT(object);
|
||||
|
||||
g_free (context->object_path);
|
||||
g_free (context->client_connection);
|
||||
|
||||
G_OBJECT_CLASS (server_context_parent_class)->finalize (object);
|
||||
@ -502,7 +544,7 @@ handle_method_call (GDBusConnection *connection,
|
||||
|
||||
g_hash_table_insert (context->keyboard_hash,
|
||||
GUINT_TO_POINTER(++keyboard_id),
|
||||
g_object_ref (serializable));
|
||||
serializable);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(u)",
|
||||
keyboard_id));
|
||||
@ -581,6 +623,23 @@ handle_method_call (GDBusConnection *connection,
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (method_name, "SetFullscreen") == 0) {
|
||||
gboolean fullscreen;
|
||||
|
||||
g_variant_get (parameters, "(b)", &fullscreen);
|
||||
|
||||
if (context->fullscreen == fullscreen) {
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
return;
|
||||
}
|
||||
context->fullscreen = fullscreen;
|
||||
if (context->window)
|
||||
set_geometry (context);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (method_name, "SetGroup") == 0) {
|
||||
gint group;
|
||||
|
||||
|
||||
@ -60,6 +60,15 @@ on_name_lost (GDBusConnection *connection,
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroyed (ServerServer *server,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -84,6 +93,7 @@ main (int argc, char **argv)
|
||||
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||
|
||||
/* preload Eek* types for EekKeyboard deserialization */
|
||||
g_type_class_ref (EEK_TYPE_KEYBOARD);
|
||||
g_type_class_ref (EEK_TYPE_SECTION);
|
||||
g_type_class_ref (EEK_TYPE_KEY);
|
||||
@ -146,6 +156,9 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
g_signal_connect (server, "destroyed", G_CALLBACK(on_destroyed), loop);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_bus_unown_name (owner_id);
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
#include "server-server.h"
|
||||
#include "server-context.h"
|
||||
|
||||
#define I_(string) g_intern_static_string (string)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_OBJECT_PATH,
|
||||
@ -29,6 +31,13 @@ enum {
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
DESTROYED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static const gchar introspection_xml[] =
|
||||
"<node>"
|
||||
" <interface name='com.redhat.Eekboard.Server'>"
|
||||
@ -43,6 +52,7 @@ static const gchar introspection_xml[] =
|
||||
" <method name='DestroyContext'>"
|
||||
" <arg direction='in' type='s' name='object_path'/>"
|
||||
" </method>"
|
||||
" <method name='Destroy'/>"
|
||||
/* signals */
|
||||
" </interface>"
|
||||
"</node>";
|
||||
@ -147,6 +157,16 @@ server_server_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (server_server_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
server_server_finalize (GObject *object)
|
||||
{
|
||||
ServerServer *server = SERVER_SERVER(object);
|
||||
|
||||
g_free (server->object_path);
|
||||
|
||||
G_OBJECT_CLASS (server_server_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
server_server_constructed (GObject *object)
|
||||
{
|
||||
@ -174,6 +194,18 @@ server_server_class_init (ServerServerClass *klass)
|
||||
gobject_class->constructed = server_server_constructed;
|
||||
gobject_class->set_property = server_server_set_property;
|
||||
gobject_class->dispose = server_server_dispose;
|
||||
gobject_class->finalize = server_server_finalize;
|
||||
|
||||
signals[DESTROYED] =
|
||||
g_signal_new (I_("destroyed"),
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
pspec = g_param_spec_string ("object-path",
|
||||
"Object-path",
|
||||
@ -248,16 +280,21 @@ server_name_vanished_callback (GDBusConnection *connection,
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
|
||||
for (head = server->context_stack; head; head = server->context_stack) {
|
||||
for (head = server->context_stack; head; ) {
|
||||
const gchar *client_connection =
|
||||
server_context_get_client_connection (head->data);
|
||||
GSList *next = g_slist_next (head);
|
||||
|
||||
if (g_strcmp0 (client_connection, name) == 0) {
|
||||
server->context_stack = g_slist_remove_link (server->context_stack,
|
||||
head);
|
||||
g_object_unref (head->data);
|
||||
g_slist_free1 (head);
|
||||
}
|
||||
|
||||
head = next;
|
||||
}
|
||||
|
||||
if (server->context_stack)
|
||||
server_context_set_enabled (server->context_stack->data, TRUE);
|
||||
}
|
||||
@ -287,6 +324,8 @@ handle_method_call (GDBusConnection *connection,
|
||||
g_hash_table_insert (server->context_hash,
|
||||
object_path,
|
||||
context);
|
||||
|
||||
/* the vanished callback is called when clients are disconnected */
|
||||
g_bus_watch_name_on_connection (server->connection,
|
||||
sender,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
@ -358,12 +397,18 @@ handle_method_call (GDBusConnection *connection,
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (method_name, "Destroy") == 0) {
|
||||
g_signal_emit_by_name (server, "destroyed", NULL);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
ServerServer *
|
||||
server_server_new (const gchar *object_path,
|
||||
GDBusConnection *connection)
|
||||
GDBusConnection *connection)
|
||||
{
|
||||
return g_object_new (SERVER_TYPE_SERVER,
|
||||
"object-path", object_path,
|
||||
|
||||
@ -34,8 +34,8 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ServerServer ServerServer;
|
||||
|
||||
ServerServer *server_server_new (const gchar *object_path,
|
||||
GDBusConnection *connection);
|
||||
ServerServer *server_server_new (const gchar *object_path,
|
||||
GDBusConnection *connection);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* SERVER_SERVER_H */
|
||||
|
||||
@ -28,7 +28,13 @@
|
||||
|
||||
#include "eek/eek-xml.h"
|
||||
#include "eek/eek-xkl.h"
|
||||
|
||||
#if HAVE_CLUTTER_GTK
|
||||
#include <clutter-gtk/clutter-gtk.h>
|
||||
#include "eek/eek-clutter.h"
|
||||
#else /* HAVE_CLUTTER_GTK */
|
||||
#include "eek/eek-gtk.h"
|
||||
#endif /* !HAVE_CLUTTER_GTK */
|
||||
|
||||
#include "xklutil.h"
|
||||
|
||||
@ -41,6 +47,7 @@ static gchar *opt_layouts = NULL;
|
||||
static gchar *opt_options = NULL;
|
||||
static gchar *opt_list = NULL;
|
||||
static guint opt_group = 0;
|
||||
static gchar *opt_theme = NULL;
|
||||
|
||||
static const GOptionEntry options[] = {
|
||||
{"load", 'l', 0, G_OPTION_ARG_STRING, &opt_load,
|
||||
@ -57,9 +64,25 @@ static const GOptionEntry options[] = {
|
||||
N_("Specify options")},
|
||||
{"group", 'g', 0, G_OPTION_ARG_INT, &opt_group,
|
||||
N_("Specify group")},
|
||||
{"theme", 't', 0, G_OPTION_ARG_STRING, &opt_theme,
|
||||
N_("Specify theme")},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
#if HAVE_CLUTTER_GTK
|
||||
static void
|
||||
on_allocation_changed (ClutterActor *stage,
|
||||
ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterActor *actor = user_data;
|
||||
clutter_actor_set_size (actor,
|
||||
box->x2 - box->x1,
|
||||
box->y2 - box->y1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
on_destroy (gpointer user_data)
|
||||
{
|
||||
@ -80,10 +103,19 @@ main (int argc, char **argv)
|
||||
{
|
||||
GOptionContext *context;
|
||||
|
||||
#if HAVE_CLUTTER_GTK
|
||||
if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
|
||||
g_printerr ("Can't init GTK with Clutter\n");
|
||||
exit (1);
|
||||
}
|
||||
#else
|
||||
if (!gtk_init_check (&argc, &argv)) {
|
||||
g_printerr ("Can't init GTK\n");
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||
|
||||
context = g_option_context_new ("eek-example-xml");
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
@ -98,6 +130,10 @@ main (int argc, char **argv)
|
||||
EekBounds bounds;
|
||||
GtkWidget *widget, *window;
|
||||
GError *error;
|
||||
#if HAVE_CLUTTER_GTK
|
||||
ClutterActor *stage, *actor;
|
||||
ClutterColor stage_color = { 0xff, 0xff, 0xff, 0xff };
|
||||
#endif
|
||||
|
||||
file = g_file_new_for_path (opt_load);
|
||||
|
||||
@ -114,11 +150,40 @@ main (int argc, char **argv)
|
||||
g_object_unref (layout);
|
||||
|
||||
eek_element_set_group (EEK_ELEMENT(keyboard), opt_group);
|
||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
|
||||
#if HAVE_CLUTTER_GTK
|
||||
widget = gtk_clutter_embed_new ();
|
||||
stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(widget));
|
||||
actor = eek_clutter_keyboard_new (keyboard);
|
||||
if (opt_theme) {
|
||||
EekTheme *theme = eek_theme_new (opt_theme, NULL, NULL);
|
||||
|
||||
eek_clutter_keyboard_set_theme (EEK_CLUTTER_KEYBOARD(actor), theme);
|
||||
g_object_unref (theme);
|
||||
}
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage), actor);
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE(stage), TRUE);
|
||||
clutter_stage_set_minimum_size (CLUTTER_STAGE(stage),
|
||||
bounds.width / 3,
|
||||
bounds.height / 3);
|
||||
g_signal_connect (stage,
|
||||
"allocation-changed",
|
||||
G_CALLBACK(on_allocation_changed),
|
||||
actor);
|
||||
#else
|
||||
widget = eek_gtk_keyboard_new (keyboard);
|
||||
if (opt_theme) {
|
||||
EekTheme *theme = eek_theme_new (opt_theme, NULL, NULL);
|
||||
|
||||
eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(widget), theme);
|
||||
g_object_unref (theme);
|
||||
}
|
||||
#endif
|
||||
g_object_unref (keyboard);
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
gtk_widget_set_size_request (widget, bounds.width, bounds.height);
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
Reference in New Issue
Block a user