added a FIXME
[moon.git] / plugin / windowless.cpp
blob2bcaab318b81d50a8713d5dac26920bcbf73d931
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->plugin = plugin;
35 UpdateWindowInfo ();
38 void
39 MoonWindowless::UpdateWindowInfo ()
41 // It appears opera doesn't do a good job of keeping the NPWindow members valid
42 // between SetWindow calls so we have to work around this by copying the members
43 // we need. This is really ugly.
45 NPWindow *window = plugin->GetWindow();
46 NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct*)window->ws_info;
47 visualid = ws_info->visual ? visualid = ws_info->visual->visualid : 0;
48 x = window->x;
49 y = window->y;
52 void
53 MoonWindowless::Resize (int width, int height)
55 bool emit_resize = false;
57 UpdateWindowInfo ();
59 if (this->width != width || this->height != height) {
60 this->width = width;
61 this->height = height;
63 emit_resize = true;
66 surface->HandleUIWindowAllocation (emit_resize);
69 void
70 MoonWindowless::SetCursor (MouseCursor cursor)
72 #if (NP_VERSION_MINOR >= NPVERS_HAS_WINDOWLESS_CURSORS)
73 NPCursor npcursor;
74 switch (cursor) {
75 case MouseCursorDefault:
76 npcursor = NPCursorAuto;
77 break;
78 case MouseCursorArrow:
79 npcursor = NPCursorPointer;
80 break;
81 case MouseCursorWait:
82 npcursor = NPCursorWait;
83 break;
84 case MouseCursorIBeam:
85 npcursor = NPCursorText;
86 break;
87 case MouseCursorStylus:
88 npcursor = NPCursorPointer; // XXX ugh...
89 break;
90 case MouseCursorEraser:
91 npcursor = NPCursorPointer; // XXX ugh...
92 break;
93 case MouseCursorNone:
94 // Silverlight display no cursor if the enumeration value is invalid (e.g. -1)
95 default:
96 npcursor = NPCursorNone;
97 break;
100 NPN_SetValue (plugin->GetInstance(), NPPVcursor, (void*)npcursor);
101 #endif
104 void
105 MoonWindowless::Invalidate (Rect r)
107 NPRect nprect;
109 // Mozilla gets seriously confused about invalidations
110 // outside the windowless bounds.
111 r = r.Intersection (Rect (0, 0, GetWidth(), GetHeight())).RoundOut ();
113 nprect.left = (uint16_t)r.x;
114 nprect.top = (uint16_t)r.y;
115 nprect.right = (uint16_t)(r.x + r.width);
116 nprect.bottom = (uint16_t)(r.y + r.height);
118 NPN_InvalidateRect (plugin->GetInstance(), &nprect);
121 void
122 MoonWindowless::ProcessUpdates ()
124 //NPN_ForceRedraw (plugin->GetInstance());
127 gboolean
128 MoonWindowless::HandleEvent (XEvent *event)
130 XEvent *xev = (XEvent*)event;
131 gboolean handled = FALSE;
133 SetCurrentDeployment ();
135 switch (xev->type) {
136 case GraphicsExpose: {
137 GdkDrawable *drawable = gdk_pixmap_foreign_new ((GdkNativeWindow)xev->xgraphicsexpose.drawable);
138 if (!drawable) {
139 drawable = gdk_window_foreign_new ((GdkNativeWindow)xev->xgraphicsexpose.drawable);
142 if (drawable) {
143 GdkVisual *visual = gdkx_visual_get (visualid);
145 if (visual) {
146 GdkEventExpose expose;
148 expose.type = GDK_EXPOSE;
149 expose.window = NULL;
150 expose.send_event = FALSE;
151 expose.area = Rect (xev->xgraphicsexpose.x,
152 xev->xgraphicsexpose.y,
153 xev->xgraphicsexpose.width,
154 xev->xgraphicsexpose.height).ToGdkRectangle ();
155 /* XXX ugh */
156 expose.region = gdk_region_rectangle (&expose.area);
158 expose.area.x = expose.area.y = 0;
160 surface->PaintToDrawable (drawable, visual, &expose, x, y, GetTransparent(), false);
161 handled = TRUE;
163 gdk_region_destroy (expose.region);
164 } else {
165 d(printf ("no gdk visual\n"));
168 g_object_unref (drawable);
169 } else {
170 d(printf ("no gdk drawable\n"));
172 break;
174 case MotionNotify: {
175 GdkEventMotion motion;
177 motion.type = GDK_MOTION_NOTIFY;
178 motion.window = NULL;
179 motion.send_event = xev->xmotion.send_event;
180 motion.x = xev->xmotion.x;
181 motion.y = xev->xmotion.y;
182 motion.axes = NULL;
183 motion.state = xev->xmotion.state;
184 motion.is_hint = xev->xmotion.is_hint;
185 motion.device = NULL; // XXX
186 motion.x_root = xev->xmotion.x_root;
187 motion.y_root = xev->xmotion.y_root;
189 handled = surface->HandleUIMotion (&motion);
190 break;
192 case ButtonPress:
193 case ButtonRelease: {
194 GdkEventButton button;
196 button.type = xev->type == ButtonPress ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
197 button.window = NULL;
198 button.send_event = xev->xbutton.send_event;
199 button.time = xev->xbutton.time;
200 button.x = xev->xbutton.x;
201 button.y = xev->xbutton.y;
202 button.x_root = xev->xbutton.x_root;
203 button.y_root = xev->xbutton.y_root;
204 button.state = xev->xbutton.state;
205 button.button = xev->xbutton.button;
206 button.axes = NULL;
208 if (xev->type == ButtonPress)
209 handled = PluginInstance::plugin_button_press_callback (NULL, &button, plugin);
210 if (!handled) {
211 if (xev->type == ButtonPress)
212 handled = surface->HandleUIButtonPress (&button);
213 else
214 handled = surface->HandleUIButtonRelease (&button);
216 break;
218 case KeyPress:
219 case KeyRelease: {
220 // make sure everything is initialized correctly (structure members vary with gdk version)
221 GdkEventKey *key = (GdkEventKey*) gdk_event_new (xev->type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
222 // gtk_im_context_xim_filter_keypress will dereference the NULL window leading to a SEGSIGV
223 key->window = GetGdkWindow ();
224 key->send_event = xev->xkey.send_event;
225 key->time = xev->xkey.time;
226 key->state = xev->xkey.state;
227 key->hardware_keycode = xev->xkey.keycode;
229 gint effective_group;
231 gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
232 xev->xkey.keycode,
233 (GdkModifierType)xev->xkey.state, // XXX
234 0, // XXX
235 &key->keyval,
236 &effective_group,
237 NULL,
238 NULL);
240 key->group = (guint8)effective_group;
242 if (xev->type == KeyPress)
243 handled = surface->HandleUIKeyPress (key);
244 else
245 handled = surface->HandleUIKeyRelease (key);
247 gdk_event_free ((GdkEvent*) key);
248 break;
250 case EnterNotify:
251 case LeaveNotify: {
252 GdkEventCrossing crossing;
254 crossing.type = xev->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
255 crossing.window = crossing.subwindow = NULL;
256 crossing.send_event = xev->xcrossing.send_event;
257 crossing.time = xev->xcrossing.time;
258 crossing.x = xev->xcrossing.x;
259 crossing.y = xev->xcrossing.y;
260 crossing.x_root = xev->xcrossing.x_root;
261 crossing.y_root = xev->xcrossing.y_root;
262 // crossing.mode = (GdkCrossingMode)xev->xcrossing.mode; // XXX
263 crossing.mode = GDK_CROSSING_NORMAL;
264 crossing.detail = (GdkNotifyType)xev->xcrossing.detail; // XXX
265 crossing.focus = xev->xcrossing.focus;
266 crossing.state = xev->xcrossing.state;
268 surface->HandleUICrossing (&crossing);
269 break;
271 case FocusIn: {
272 surface->HandleUIFocusIn (NULL);
273 break;
276 case FocusOut: {
277 surface->HandleUIFocusOut (NULL);
278 break;
280 default:
281 d(printf ("Unhandled Xlib event %d\n", xev->type));
282 break;
285 return handled;
288 void
289 MoonWindowless::Show ()
291 // nothing needed here
294 void
295 MoonWindowless::Hide ()
297 // nothing needed here
300 void
301 MoonWindowless::EnableEvents (bool first)
303 // nothing needed here, NPAPI pushes events through
304 // HandleEvent.
307 void
308 MoonWindowless::DisableEvents ()
310 // nothing needed here, NPAPI pushes events through
311 // HandleEvent.
314 void
315 MoonWindowless::GrabFocus ()
317 // we can't grab focus - the browser handles that.
320 bool
321 MoonWindowless::HasFocus ()
323 // XXX maybe we should track the focus in/out events?
324 return false;
327 void
328 MoonWindowless::SetSurface (Surface *s)
330 MoonWindow::SetSurface (s);
331 s->HandleUIWindowAvailable ();
334 GdkWindow*
335 MoonWindowless::GetGdkWindow ()
337 GdkNativeWindow window;
338 NPN_GetValue (plugin->GetInstance(), NPNVnetscapeWindow, (void*)&window);
339 GdkWindow *gdk = gdk_window_foreign_new (window);
340 return gdk;