2009-08-11 Chris Toshok <toshok@ximian.com>
[moon.git] / plugin / windowless.cpp
bloba7b5cf2df973087814521d9e1bb0bf801c6e1e2a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * windowless.cpp: Windowsless Surface subclass
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
14 #include <config.h>
16 #include "windowless.h"
18 #define Visual _XxVisual
19 #define Region _XxRegion
20 #include <gdk/gdkx.h>
21 #undef Visual
22 #undef Region
24 #ifdef DEBUG
25 #define d(x) x
26 #else
27 #define d(x)
28 #endif
30 MoonWindowless::MoonWindowless (int width, int height, PluginInstance *plugin)
31 : MoonWindow (width, height)
33 this->deployment = Deployment::GetCurrent ();
34 this->plugin = plugin;
36 UpdateWindowInfo ();
39 void
40 MoonWindowless::UpdateWindowInfo ()
42 // It appears opera doesn't do a good job of keeping the NPWindow members valid
43 // between SetWindow calls so we have to work around this by copying the members
44 // we need. This is really ugly.
46 NPWindow *window = plugin->GetWindow();
47 NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct*)window->ws_info;
48 visualid = ws_info->visual ? visualid = ws_info->visual->visualid : 0;
49 x = window->x;
50 y = window->y;
53 void
54 MoonWindowless::Resize (int width, int height)
56 bool emit_resize = false;
58 UpdateWindowInfo ();
60 if (this->width != width || this->height != height) {
61 this->width = width;
62 this->height = height;
64 emit_resize = true;
67 surface->HandleUIWindowAllocation (emit_resize);
70 void
71 MoonWindowless::SetCursor (MouseCursor cursor)
73 #if (NP_VERSION_MINOR >= NPVERS_HAS_WINDOWLESS_CURSORS)
74 NPCursor npcursor;
75 switch (cursor) {
76 case MouseCursorDefault:
77 npcursor = NPCursorAuto;
78 break;
79 case MouseCursorArrow:
80 npcursor = NPCursorPointer;
81 break;
82 case MouseCursorWait:
83 npcursor = NPCursorWait;
84 break;
85 case MouseCursorIBeam:
86 npcursor = NPCursorText;
87 break;
88 case MouseCursorStylus:
89 npcursor = NPCursorPointer; // XXX ugh...
90 break;
91 case MouseCursorEraser:
92 npcursor = NPCursorPointer; // XXX ugh...
93 break;
94 case MouseCursorNone:
95 // Silverlight display no cursor if the enumeration value is invalid (e.g. -1)
96 default:
97 npcursor = NPCursorNone;
98 break;
101 NPN_SetValue (plugin->GetInstance(), NPPVcursor, (void*)npcursor);
102 #endif
105 void
106 MoonWindowless::Invalidate (Rect r)
108 NPRect nprect;
110 // Mozilla gets seriously confused about invalidations
111 // outside the windowless bounds.
112 r = r.Intersection (Rect (0, 0, GetWidth(), GetHeight())).RoundOut ();
114 nprect.left = (uint16_t)r.x;
115 nprect.top = (uint16_t)r.y;
116 nprect.right = (uint16_t)(r.x + r.width);
117 nprect.bottom = (uint16_t)(r.y + r.height);
119 NPN_InvalidateRect (plugin->GetInstance(), &nprect);
122 void
123 MoonWindowless::ProcessUpdates ()
125 //NPN_ForceRedraw (plugin->GetInstance());
128 gboolean
129 MoonWindowless::HandleEvent (XEvent *event)
131 XEvent *xev = (XEvent*)event;
132 gboolean handled = FALSE;
134 Deployment::SetCurrent (deployment);
136 switch (xev->type) {
137 case GraphicsExpose: {
138 GdkDrawable *drawable = gdk_pixmap_foreign_new ((GdkNativeWindow)xev->xgraphicsexpose.drawable);
139 if (!drawable) {
140 drawable = gdk_window_foreign_new ((GdkNativeWindow)xev->xgraphicsexpose.drawable);
143 if (drawable) {
144 GdkVisual *visual = gdkx_visual_get (visualid);
146 if (visual) {
147 GdkEventExpose expose;
149 expose.type = GDK_EXPOSE;
150 expose.window = NULL;
151 expose.send_event = FALSE;
152 expose.area = Rect (xev->xgraphicsexpose.x,
153 xev->xgraphicsexpose.y,
154 xev->xgraphicsexpose.width,
155 xev->xgraphicsexpose.height).ToGdkRectangle ();
156 /* XXX ugh */
157 expose.region = gdk_region_rectangle (&expose.area);
159 expose.area.x = expose.area.y = 0;
161 surface->PaintToDrawable (drawable, visual, &expose, x, y, GetTransparent(), false);
162 handled = TRUE;
164 gdk_region_destroy (expose.region);
165 } else {
166 d(printf ("no gdk visual\n"));
169 g_object_unref (drawable);
170 } else {
171 d(printf ("no gdk drawable\n"));
173 break;
175 case MotionNotify: {
176 GdkEventMotion motion;
178 motion.type = GDK_MOTION_NOTIFY;
179 motion.window = NULL;
180 motion.send_event = xev->xmotion.send_event;
181 motion.x = xev->xmotion.x;
182 motion.y = xev->xmotion.y;
183 motion.axes = NULL;
184 motion.state = xev->xmotion.state;
185 motion.is_hint = xev->xmotion.is_hint;
186 motion.device = NULL; // XXX
187 motion.x_root = xev->xmotion.x_root;
188 motion.y_root = xev->xmotion.y_root;
190 handled = surface->HandleUIMotion (&motion);
191 break;
193 case ButtonPress:
194 case ButtonRelease: {
195 GdkEventButton button;
197 button.type = xev->type == ButtonPress ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
198 button.window = NULL;
199 button.send_event = xev->xbutton.send_event;
200 button.time = xev->xbutton.time;
201 button.x = xev->xbutton.x;
202 button.y = xev->xbutton.y;
203 button.x_root = xev->xbutton.x_root;
204 button.y_root = xev->xbutton.y_root;
205 button.state = xev->xbutton.state;
206 button.button = xev->xbutton.button;
207 button.axes = NULL;
209 if (xev->type == ButtonPress)
210 handled = PluginInstance::plugin_button_press_callback (NULL, &button, plugin);
211 if (!handled) {
212 if (xev->type == ButtonPress)
213 handled = surface->HandleUIButtonPress (&button);
214 else
215 handled = surface->HandleUIButtonRelease (&button);
217 break;
219 case KeyPress:
220 case KeyRelease: {
221 // make sure everything is initialized correctly (structure members vary with gdk version)
222 GdkEventKey *key = (GdkEventKey*) gdk_event_new (xev->type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
223 // gtk_im_context_xim_filter_keypress will dereference the NULL window leading to a SEGSIGV
224 key->window = GetGdkWindow ();
225 key->send_event = xev->xkey.send_event;
226 key->time = xev->xkey.time;
227 key->state = xev->xkey.state;
228 key->hardware_keycode = xev->xkey.keycode;
230 gint effective_group;
232 gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
233 xev->xkey.keycode,
234 (GdkModifierType)xev->xkey.state, // XXX
235 0, // XXX
236 &key->keyval,
237 &effective_group,
238 NULL,
239 NULL);
241 key->group = (guint8)effective_group;
243 if (xev->type == KeyPress)
244 handled = surface->HandleUIKeyPress (key);
245 else
246 handled = surface->HandleUIKeyRelease (key);
248 gdk_event_free ((GdkEvent*) key);
249 break;
251 case EnterNotify:
252 case LeaveNotify: {
253 GdkEventCrossing crossing;
255 crossing.type = xev->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
256 crossing.window = crossing.subwindow = NULL;
257 crossing.send_event = xev->xcrossing.send_event;
258 crossing.time = xev->xcrossing.time;
259 crossing.x = xev->xcrossing.x;
260 crossing.y = xev->xcrossing.y;
261 crossing.x_root = xev->xcrossing.x_root;
262 crossing.y_root = xev->xcrossing.y_root;
263 // crossing.mode = (GdkCrossingMode)xev->xcrossing.mode; // XXX
264 crossing.mode = GDK_CROSSING_NORMAL;
265 crossing.detail = (GdkNotifyType)xev->xcrossing.detail; // XXX
266 crossing.focus = xev->xcrossing.focus;
267 crossing.state = xev->xcrossing.state;
269 surface->HandleUICrossing (&crossing);
270 break;
272 case FocusIn: {
273 surface->HandleUIFocusIn (NULL);
274 break;
277 case FocusOut: {
278 surface->HandleUIFocusOut (NULL);
279 break;
281 default:
282 d(printf ("Unhandled Xlib event %d\n", xev->type));
283 break;
286 return handled;
289 void
290 MoonWindowless::Show ()
292 // nothing needed here
295 void
296 MoonWindowless::Hide ()
298 // nothing needed here
301 void
302 MoonWindowless::EnableEvents (bool first)
304 // nothing needed here, NPAPI pushes events through
305 // HandleEvent.
308 void
309 MoonWindowless::DisableEvents ()
311 // nothing needed here, NPAPI pushes events through
312 // HandleEvent.
315 void
316 MoonWindowless::GrabFocus ()
318 // we can't grab focus - the browser handles that.
321 bool
322 MoonWindowless::HasFocus ()
324 // XXX maybe we should track the focus in/out events?
325 return false;
328 void
329 MoonWindowless::SetSurface (Surface *s)
331 MoonWindow::SetSurface (s);
332 s->HandleUIWindowAvailable ();
335 GdkWindow*
336 MoonWindowless::GetGdkWindow ()
338 GdkNativeWindow window;
339 NPN_GetValue (plugin->GetInstance(), NPNVnetscapeWindow, (void*)&window);
340 GdkWindow *gdk = gdk_window_foreign_new (window);
341 return gdk;