aboutsummaryrefslogtreecommitdiffstats
path: root/embed
diff options
context:
space:
mode:
Diffstat (limited to 'embed')
-rw-r--r--embed/ephy-embed-event.c1
-rw-r--r--embed/ephy-embed-event.h1
-rw-r--r--embed/ephy-embed-popup-bw.c13
-rw-r--r--embed/ephy-embed.c11
-rw-r--r--embed/ephy-embed.h2
-rw-r--r--embed/mozilla/EventContext.cpp58
-rw-r--r--embed/mozilla/EventContext.h1
-rw-r--r--embed/mozilla/mozilla-embed.cpp73
8 files changed, 158 insertions, 2 deletions
diff --git a/embed/ephy-embed-event.c b/embed/ephy-embed-event.c
index 5ee7d2781..3df03f3dc 100644
--- a/embed/ephy-embed-event.c
+++ b/embed/ephy-embed-event.c
@@ -87,6 +87,7 @@ ephy_embed_event_init (EphyEmbedEvent *event)
event->priv->props = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, free_g_value);
+ event->mouse_button = -1;
}
static void
diff --git a/embed/ephy-embed-event.h b/embed/ephy-embed-event.h
index 9291ae6ae..44448cce6 100644
--- a/embed/ephy-embed-event.h
+++ b/embed/ephy-embed-event.h
@@ -60,6 +60,7 @@ struct EphyEmbedEvent
guint mouse_button;
guint context;
guint x, y;
+ guint keycode;
};
struct EphyEmbedEventClass
diff --git a/embed/ephy-embed-popup-bw.c b/embed/ephy-embed-popup-bw.c
index 553f73205..f72e44e6e 100644
--- a/embed/ephy-embed-popup-bw.c
+++ b/embed/ephy-embed-popup-bw.c
@@ -162,6 +162,17 @@ ephy_embed_popup_bw_new (BonoboWindow *window)
}
static void
+popup_menu_at_coords (GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
+ gpointer user_data)
+{
+ EphyEmbedEvent *event = user_data;
+
+ *x = event->x;
+ *y = event->y;
+ *push_in = FALSE;
+}
+
+static void
ephy_embed_popup_bw_show_impl (EphyEmbedPopup *pp,
EphyEmbed *embed)
{
@@ -181,7 +192,7 @@ ephy_embed_popup_bw_show_impl (EphyEmbedPopup *pp,
ephy_embed_popup_get_popup_path (EPHY_EMBED_POPUP (p)));
gtk_menu_popup (GTK_MENU (p->priv->menu),
- NULL, NULL, NULL, NULL,
+ NULL, NULL, button == 2 ? popup_menu_at_coords : NULL, event,
button, gtk_get_current_event_time ());
}
diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c
index 3360e9e67..ebc33b833 100644
--- a/embed/ephy-embed.c
+++ b/embed/ephy-embed.c
@@ -29,6 +29,7 @@
enum
{
NEW_WINDOW,
+ CONTEXT_MENU,
LINK_MESSAGE,
FAVICON,
JS_STATUS,
@@ -108,6 +109,16 @@ ephy_embed_base_init (gpointer g_class)
G_TYPE_NONE,
1,
G_TYPE_STRING);
+ ephy_embed_signals[CONTEXT_MENU] =
+ g_signal_new ("ge_context_menu",
+ EPHY_EMBED_TYPE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EphyEmbedClass, context_menu),
+ NULL, NULL,
+ ephy_marshal_INT__OBJECT,
+ G_TYPE_INT,
+ 1,
+ G_TYPE_OBJECT);
ephy_embed_signals[FAVICON] =
g_signal_new ("ge_favicon",
EPHY_EMBED_TYPE,
diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h
index a80d11d80..6371dea98 100644
--- a/embed/ephy-embed.h
+++ b/embed/ephy-embed.h
@@ -164,6 +164,8 @@ struct EphyEmbedClass
{
GTypeInterface base_iface;
+ gint (* context_menu) (EphyEmbed *embed,
+ EphyEmbedEvent *event);
void (* favicon) (EphyEmbed *embed,
const char *location);
void (* link_message) (EphyEmbed *embed,
diff --git a/embed/mozilla/EventContext.cpp b/embed/mozilla/EventContext.cpp
index 7fa44acc0..229f8d3be 100644
--- a/embed/mozilla/EventContext.cpp
+++ b/embed/mozilla/EventContext.cpp
@@ -586,6 +586,64 @@ nsresult EventContext::GetMouseEventInfo (nsIDOMMouseEvent *aMouseEvent, EphyEmb
return NS_OK;
}
+nsresult EventContext::GetKeyEventInfo (nsIDOMKeyEvent *aKeyEvent, EphyEmbedEvent *info)
+{
+ nsresult rv;
+
+ PRUint32 keyCode;
+ rv = aKeyEvent->GetKeyCode(&keyCode);
+ if (NS_FAILED(rv)) return rv;
+ info->keycode = keyCode;
+
+ nsCOMPtr<nsIDOMEventTarget> target;
+ rv = aKeyEvent->GetTarget(getter_AddRefs(target));
+ if (NS_FAILED(rv) || !target) return NS_ERROR_FAILURE;
+
+ /* Calculate the node coordinates relative to the widget origin */
+ nsCOMPtr<nsIDOMNSHTMLElement> elem = do_QueryInterface(target, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ PRInt32 x = 0, y = 0;
+ while (elem)
+ {
+ PRInt32 val;
+ elem->GetOffsetTop(&val); y += val;
+ elem->GetScrollTop(&val); y -= val;
+ elem->GetOffsetLeft(&val); x += val;
+ elem->GetScrollLeft(&val); x -= val;
+
+ nsCOMPtr<nsIDOMElement> parent;
+ elem->GetOffsetParent(getter_AddRefs(parent));
+ elem = do_QueryInterface(parent, &rv);
+ }
+ info->x = x;
+ info->y = y;
+
+ /* Context */
+ rv = GetEventContext (target, info);
+ if (NS_FAILED(rv)) return rv;
+
+ /* Get the modifier */
+
+ PRBool mod_key;
+
+ info->modifier = 0;
+
+ aKeyEvent->GetAltKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_MOD1_MASK;
+
+ aKeyEvent->GetShiftKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_SHIFT_MASK;
+
+ aKeyEvent->GetMetaKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_Meta_L;
+
+ aKeyEvent->GetCtrlKey(&mod_key);
+ if (mod_key) info->modifier |= GDK_CONTROL_MASK;
+
+ return NS_OK;
+}
+
nsresult EventContext::IsPageFramed (nsIDOMNode *node, PRBool *Framed)
{
nsresult result;
diff --git a/embed/mozilla/EventContext.h b/embed/mozilla/EventContext.h
index 8025fb353..54c51b035 100644
--- a/embed/mozilla/EventContext.h
+++ b/embed/mozilla/EventContext.h
@@ -45,6 +45,7 @@ public:
nsresult Init (EphyWrapper *wrapper);
nsresult GetMouseEventInfo (nsIDOMMouseEvent *event, EphyEmbedEvent *info);
+ nsresult GetKeyEventInfo (nsIDOMKeyEvent *event, EphyEmbedEvent *info);
nsresult GetTargetDocument (nsIDOMDocument **domDoc);
private:
diff --git a/embed/mozilla/mozilla-embed.cpp b/embed/mozilla/mozilla-embed.cpp
index f578fb198..95dd0190e 100644
--- a/embed/mozilla/mozilla-embed.cpp
+++ b/embed/mozilla/mozilla-embed.cpp
@@ -206,6 +206,9 @@ mozilla_embed_security_change_cb (GtkMozEmbed *embed,
guint state, MozillaEmbed *membed);
static EmbedSecurityLevel
mozilla_embed_security_level (MozillaEmbed *membed);
+static gint
+mozilla_embed_dom_key_down_cb (GtkMozEmbed *embed, gpointer dom_event,
+ MozillaEmbed *membed);
/* signals to connect on each embed widget */
static const struct
@@ -228,6 +231,7 @@ signal_connections[] =
{ "size_to", (void *) mozilla_embed_size_to_cb },
{ "new_window", (void *) mozilla_embed_new_window_cb },
{ "security_change", (void *) mozilla_embed_security_change_cb },
+ { "dom_key_down", (void *) mozilla_embed_dom_key_down_cb },
/* terminator -- must be last in the list! */
{ NULL, NULL }
@@ -1312,6 +1316,63 @@ mozilla_embed_visibility_cb (GtkMozEmbed *embed, gboolean visibility,
}
}
+static gint
+mozilla_embed_dom_key_down_cb (GtkMozEmbed *embed, gpointer dom_event,
+ MozillaEmbed *membed)
+{
+ nsCOMPtr<nsIDOMKeyEvent> ev = static_cast<nsIDOMKeyEvent*>(dom_event);
+ if (!ev)
+ {
+ return FALSE;
+ }
+
+ EphyWrapper *wrapper = MOZILLA_EMBED(membed)->priv->wrapper;
+ g_return_val_if_fail (wrapper != NULL, G_FAILED);
+
+ EphyEmbedEvent *info;
+ info = ephy_embed_event_new ();
+
+ gboolean ret = FALSE;
+
+ // Just check for Shift-F10 so that we know to popup the context menu.
+ //
+ // The DOM_VK_* keycodes are not compatible with the keycodes defined
+ // in GDK, so making a generic dom_key_down signal is probably not
+ // worth the trouble.
+
+ nsresult rv;
+ EventContext ctx;
+ ctx.Init (wrapper);
+ rv = ctx.GetKeyEventInfo (ev, info);
+ if (NS_SUCCEEDED(rv) &&
+ (info->keycode == nsIDOMKeyEvent::DOM_VK_F10 &&
+ info->modifier == GDK_SHIFT_MASK))
+ {
+ // Translate relative coordinates to absolute values, and try
+ // to avoid covering links by adding a little offset.
+
+ int x, y;
+ gdk_window_get_origin (GTK_WIDGET(membed)->window, &x, &y);
+ info->x += x + 6;
+ info->y += y + 6;
+
+ nsCOMPtr<nsIDOMDocument> doc;
+ rv = ctx.GetTargetDocument (getter_AddRefs(doc));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = wrapper->PushTargetDocument (doc);
+ if (NS_SUCCEEDED(rv))
+ {
+ g_signal_emit_by_name (membed, "ge_context_menu", info, &ret);
+ wrapper->PopTargetDocument ();
+ }
+ }
+ }
+
+ g_object_unref (info);
+ return ret;
+}
+
static void
mozilla_embed_destroy_brsr_cb (GtkMozEmbed *embed,
MozillaEmbed *membed)
@@ -1371,8 +1432,18 @@ static gint
mozilla_embed_dom_mouse_down_cb (GtkMozEmbed *embed, gpointer dom_event,
MozillaEmbed *membed)
{
- return mozilla_embed_emit_mouse_signal
+ int ret;
+
+ ret = mozilla_embed_emit_mouse_signal
(membed, dom_event, "ge_dom_mouse_down");
+
+ if (!ret)
+ {
+ ret = mozilla_embed_emit_mouse_signal
+ (membed, dom_event, "ge_context_menu");
+ }
+
+ return ret;
}
static void