~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to clutter/win32/clutter-stage-win32.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * Lesser General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the
18
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
 
 * Boston, MA 02111-1307, USA.
 
17
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 
18
 *
 
19
 *
20
20
 */
21
21
 
22
22
#ifdef HAVE_CONFIG_H
45
45
#include <windows.h>
46
46
 
47
47
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
48
 
         
 
48
 
49
49
G_DEFINE_TYPE_WITH_CODE (ClutterStageWin32,
50
50
                         clutter_stage_win32,
51
 
                         CLUTTER_TYPE_GROUP,
 
51
                         G_TYPE_OBJECT,
52
52
                         G_IMPLEMENT_INTERFACE
53
53
                         (CLUTTER_TYPE_STAGE_WINDOW,
54
54
                          clutter_stage_window_iface_init));
55
55
 
56
56
static void
57
 
clutter_stage_win32_show (ClutterActor *actor)
58
 
{
59
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor);
60
 
 
61
 
  if (stage_win32->hwnd)
62
 
    ShowWindow (stage_win32->hwnd, SW_SHOW);
63
 
}
64
 
 
65
 
static void
66
 
clutter_stage_win32_hide (ClutterActor *actor)
67
 
{
68
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor);
69
 
 
70
 
  if (stage_win32->hwnd)
71
 
    ShowWindow (stage_win32->hwnd, SW_HIDE);
72
 
}
73
 
 
74
 
static void
75
 
clutter_stage_win32_get_preferred_width (ClutterActor  *self,
76
 
                                         gfloat         for_height,
77
 
                                         gfloat        *min_width_p,
78
 
                                         gfloat        *natural_width_p)
79
 
{
80
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (self);
81
 
  int width;
82
 
 
83
 
  /* If we're in fullscreen mode then return the size of the screen
84
 
     instead */
85
 
  if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN))
86
 
    width = stage_win32->fullscreen_rect.right
87
 
          - stage_win32->fullscreen_rect.left;
88
 
  else
89
 
    width = stage_win32->win_width;
90
 
 
91
 
  if (min_width_p)
92
 
    *min_width_p = width;
93
 
 
94
 
  if (natural_width_p)
95
 
    *natural_width_p = width;
96
 
}
97
 
 
98
 
static void
99
 
clutter_stage_win32_get_preferred_height (ClutterActor  *self,
100
 
                                          gfloat         for_width,
101
 
                                          gfloat        *min_height_p,
102
 
                                          gfloat        *natural_height_p)
103
 
{
104
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (self);
105
 
  int height;
106
 
 
107
 
  /* If we're in fullscreen mode then return the size of the screen
108
 
     instead */
109
 
  if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN))
110
 
    height = stage_win32->fullscreen_rect.bottom
111
 
           - stage_win32->fullscreen_rect.top;
112
 
  else
113
 
    height = stage_win32->win_height;
114
 
 
115
 
  if (min_height_p)
116
 
    *min_height_p = height;
117
 
 
118
 
  if (natural_height_p)
119
 
    *natural_height_p = height;
 
57
clutter_stage_win32_show (ClutterStageWindow *stage_window,
 
58
                          gboolean            do_raise)
 
59
{
 
60
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
61
 
 
62
  if (stage_win32->hwnd)
 
63
    {
 
64
      ShowWindow (stage_win32->hwnd, do_raise ? SW_SHOW : SW_SHOWNA);
 
65
 
 
66
      clutter_stage_ensure_viewport (CLUTTER_STAGE (stage_win32->wrapper));
 
67
      clutter_actor_map (CLUTTER_ACTOR (stage_win32->wrapper));
 
68
    }
 
69
}
 
70
 
 
71
static void
 
72
clutter_stage_win32_hide (ClutterStageWindow *stage_window)
 
73
{
 
74
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
75
 
 
76
  if (stage_win32->hwnd)
 
77
    {
 
78
      clutter_actor_unmap (CLUTTER_ACTOR (stage_win32->wrapper));
 
79
      ShowWindow (stage_win32->hwnd, SW_HIDE);
 
80
    }
 
81
}
 
82
 
 
83
static void
 
84
clutter_stage_win32_get_geometry (ClutterStageWindow *stage_window,
 
85
                                  ClutterGeometry    *geometry)
 
86
{
 
87
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
88
 
 
89
  if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN))
 
90
    {
 
91
      geometry->width = (stage_win32->fullscreen_rect.right
 
92
                         - stage_win32->fullscreen_rect.left);
 
93
      geometry->height = (stage_win32->fullscreen_rect.bottom
 
94
                          - stage_win32->fullscreen_rect.top);
 
95
      return;
 
96
    }
 
97
 
 
98
  geometry->width = stage_win32->win_width;
 
99
  geometry->height = stage_win32->win_height;
120
100
}
121
101
 
122
102
static void
179
159
}
180
160
 
181
161
static void
182
 
clutter_stage_win32_allocate (ClutterActor           *self,
183
 
                              const ClutterActorBox  *box,
184
 
                              ClutterAllocationFlags  flags)
 
162
clutter_stage_win32_resize (ClutterStageWindow *stage_window,
 
163
                            gint                width,
 
164
                            gint                height)
185
165
{
186
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (self);
187
 
  gint new_width, new_height;
188
 
 
189
 
  new_width  = ABS (box->x2 - box->x1);
190
 
  new_height = ABS (box->y2 - box->y1);
191
 
 
192
 
  if (new_width != stage_win32->win_width ||
193
 
      new_height != stage_win32->win_height)
 
166
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
167
  gboolean resize;
 
168
 
 
169
  resize = clutter_stage_get_user_resizable (stage_win32->wrapper);
 
170
 
 
171
  if (width != stage_win32->win_width || height != stage_win32->win_height)
194
172
    {
195
173
      /* Ignore size requests if we are in full screen mode */
196
174
      if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN) == 0)
197
 
        {
198
 
          stage_win32->win_width = new_width;
199
 
          stage_win32->win_height = new_height;
200
 
 
201
 
          if (stage_win32->hwnd != NULL && !stage_win32->is_foreign_win)
202
 
            {
203
 
              int full_width, full_height;
204
 
 
205
 
              get_full_window_size (stage_win32,
206
 
                                    new_width, new_height,
207
 
                                    &full_width, &full_height);
208
 
 
209
 
              SetWindowPos (stage_win32->hwnd, NULL,
210
 
                            0, 0,
211
 
                            full_width, full_height,
212
 
                            SWP_NOZORDER | SWP_NOMOVE);
213
 
            }
214
 
        }
 
175
        {
 
176
          stage_win32->win_width = width;
 
177
          stage_win32->win_height = height;
 
178
 
 
179
          if (stage_win32->hwnd != NULL && !stage_win32->is_foreign_win)
 
180
            {
 
181
              int full_width, full_height;
 
182
 
 
183
              get_full_window_size (stage_win32,
 
184
                                    width, height,
 
185
                                    &full_width, &full_height);
 
186
 
 
187
              SetWindowPos (stage_win32->hwnd, NULL,
 
188
                            0, 0,
 
189
                            full_width, full_height,
 
190
                            SWP_NOZORDER | SWP_NOMOVE);
 
191
            }
 
192
        }
215
193
 
216
194
      CLUTTER_SET_PRIVATE_FLAGS (stage_win32->wrapper,
217
 
                                 CLUTTER_ACTOR_SYNC_MATRICES);
 
195
                                 CLUTTER_ACTOR_SYNC_MATRICES);
218
196
    }
219
 
 
220
 
  CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)
221
 
    ->allocate (self, box, flags);
222
197
}
223
198
 
224
199
static void
226
201
                               const gchar        *title)
227
202
{
228
203
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
229
 
  wchar_t *wtitle;
230
204
 
231
205
  /* Empty window titles not allowed, so set it to just a period. */
232
206
  if (title == NULL || !title[0])
233
207
    title = ".";
234
208
  
235
 
  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
236
 
  SetWindowTextW (stage_win32->hwnd, wtitle);
237
 
  g_free (wtitle);
 
209
  if (stage_win32->wtitle != NULL)
 
210
    g_free (stage_win32->wtitle);
 
211
  stage_win32->wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
 
212
 
 
213
  /* If the window is not yet created, the title will be set during the
 
214
     window creation */
 
215
  if (stage_win32->hwnd != NULL)
 
216
    SetWindowTextW (stage_win32->hwnd, stage_win32->wtitle);
 
217
}
 
218
 
 
219
void
 
220
_clutter_stage_win32_update_cursor (ClutterStageWin32 *stage_win32)
 
221
{
 
222
  HCURSOR cursor;
 
223
 
 
224
  if (stage_win32->is_cursor_visible)
 
225
    cursor = (HCURSOR) GetClassLongPtrW (stage_win32->hwnd, GCL_HCURSOR);
 
226
  else
 
227
    {
 
228
      ClutterBackend *backend = clutter_get_default_backend ();
 
229
      /* The documentation implies that we can just use
 
230
         SetCursor(NULL) to get rid of the cursor but apparently this
 
231
         doesn't work very well so instead we create an invisible
 
232
         cursor */
 
233
      cursor = _clutter_backend_win32_get_invisible_cursor (backend);
 
234
    }
 
235
 
 
236
  SetCursor (cursor);
 
237
}
 
238
 
 
239
static void
 
240
clutter_stage_win32_set_cursor_visible (ClutterStageWindow *stage_window,
 
241
                                        gboolean            cursor_visible)
 
242
{
 
243
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
244
 
 
245
  if (stage_win32->is_cursor_visible != cursor_visible)
 
246
    {
 
247
      POINT cursor_pos;
 
248
      RECT client_rect;
 
249
 
 
250
      stage_win32->is_cursor_visible = cursor_visible;
 
251
 
 
252
      /* If the cursor is already over the client area of the window
 
253
         then we need to update it immediately */
 
254
      GetCursorPos (&cursor_pos);
 
255
      if (WindowFromPoint (cursor_pos) == stage_win32->hwnd &&
 
256
          ScreenToClient (stage_win32->hwnd, &cursor_pos) &&
 
257
          GetClientRect (stage_win32->hwnd, &client_rect) &&
 
258
          cursor_pos.x >= client_rect.left &&
 
259
          cursor_pos.y >= client_rect.top &&
 
260
          cursor_pos.x < client_rect.right &&
 
261
          cursor_pos.y < client_rect.bottom)
 
262
        _clutter_stage_win32_update_cursor (stage_win32);
 
263
    }
238
264
}
239
265
 
240
266
static LONG
296
322
                      | (old_style & WS_VISIBLE));
297
323
      /* Update the window size */
298
324
      if (value)
299
 
        {
300
 
          get_fullscreen_rect (stage_win32);
301
 
          SetWindowPos (hwnd, HWND_TOP,
302
 
                        stage_win32->fullscreen_rect.left,
303
 
                        stage_win32->fullscreen_rect.top,
304
 
                        stage_win32->fullscreen_rect.right
305
 
                        - stage_win32->fullscreen_rect.left,
306
 
                        stage_win32->fullscreen_rect.bottom
307
 
                        - stage_win32->fullscreen_rect.top,
308
 
                        0);
309
 
        }
 
325
        {
 
326
          get_fullscreen_rect (stage_win32);
 
327
          SetWindowPos (hwnd, HWND_TOP,
 
328
                        stage_win32->fullscreen_rect.left,
 
329
                        stage_win32->fullscreen_rect.top,
 
330
                        stage_win32->fullscreen_rect.right
 
331
                        - stage_win32->fullscreen_rect.left,
 
332
                        stage_win32->fullscreen_rect.bottom
 
333
                        - stage_win32->fullscreen_rect.top,
 
334
                        0);
 
335
        }
310
336
      else
311
 
        {
312
 
          int full_width, full_height;
313
 
 
314
 
          get_full_window_size (stage_win32,
315
 
                                stage_win32->win_width,
316
 
                                stage_win32->win_height,
317
 
                                &full_width, &full_height);
318
 
 
319
 
          SetWindowPos (stage_win32->hwnd, NULL,
320
 
                        0, 0,
321
 
                        full_width, full_height,
322
 
                        SWP_NOZORDER | SWP_NOMOVE);
323
 
        }
 
337
        {
 
338
          int full_width, full_height;
 
339
 
 
340
          get_full_window_size (stage_win32,
 
341
                                stage_win32->win_width,
 
342
                                stage_win32->win_height,
 
343
                                &full_width, &full_height);
 
344
 
 
345
          SetWindowPos (stage_win32->hwnd, NULL,
 
346
                        0, 0,
 
347
                        full_width, full_height,
 
348
                        SWP_NOZORDER | SWP_NOMOVE);
 
349
        }
324
350
 
325
351
      CLUTTER_SET_PRIVATE_FLAGS (stage_win32->wrapper,
326
352
                                 CLUTTER_ACTOR_SYNC_MATRICES);
360
386
}
361
387
 
362
388
static gboolean
363
 
clutter_stage_win32_check_gl_version ()
364
 
{
365
 
  const char *version_string, *major_end, *minor_end;
366
 
  int major = 0, minor = 0;
367
 
  
368
 
  /* Get the OpenGL version number */
369
 
  if ((version_string = (const char *) glGetString (GL_VERSION)) == NULL)
370
 
    return FALSE;
371
 
 
372
 
  /* Extract the major number */
373
 
  for (major_end = version_string; *major_end >= '0'
374
 
         && *major_end <= '9'; major_end++)
375
 
    major = (major * 10) + *major_end - '0';
376
 
  /* If there were no digits or the major number isn't followed by a
377
 
     dot then it is invalid */
378
 
  if (major_end == version_string || *major_end != '.')
379
 
    return FALSE;
380
 
  
381
 
  /* Extract the minor number */
382
 
  for (minor_end = major_end + 1; *minor_end >= '0'
383
 
         && *minor_end <= '9'; minor_end++)
384
 
    minor = (minor * 10) + *minor_end - '0';
385
 
  /* If there were no digits or there is an unexpected character then
386
 
     it is invalid */
387
 
  if (minor_end == major_end + 1
388
 
      || (*minor_end && *minor_end != ' ' && *minor_end != '.'))
389
 
    return FALSE;
390
 
 
391
 
  /* Accept OpenGL 1.2 or later */
392
 
  return major > 1 || (major == 1 && minor >= 2);
393
 
}
394
 
 
395
 
static gboolean
396
 
clutter_stage_win32_pixel_format_is_better (const PIXELFORMATDESCRIPTOR *pfa,
397
 
                                            const PIXELFORMATDESCRIPTOR *pfb)
398
 
{
399
 
  /* Always prefer a format with a stencil buffer */
400
 
  if (pfa->cStencilBits == 0)
401
 
    {
402
 
      if (pfb->cStencilBits > 0)
403
 
        return TRUE;
404
 
    }
405
 
  else if (pfb->cStencilBits == 0)
406
 
    return FALSE;
407
 
 
408
 
  /* Prefer a bigger color buffer */
409
 
  if (pfb->cColorBits > pfa->cColorBits)
410
 
    return TRUE;
411
 
  else if (pfb->cColorBits < pfa->cColorBits)
412
 
    return FALSE;
413
 
 
414
 
  /* Prefer a bigger depth buffer */
415
 
  return pfb->cDepthBits > pfa->cDepthBits;
416
 
}
417
 
 
418
 
static int
419
 
clutter_stage_win32_choose_pixel_format (HDC dc, PIXELFORMATDESCRIPTOR *pfd)
420
 
{
421
 
  int i, num_formats, best_pf = 0;
422
 
  PIXELFORMATDESCRIPTOR best_pfd;
423
 
 
424
 
  num_formats = DescribePixelFormat (dc, 0, sizeof (best_pfd), NULL);
425
 
 
426
 
  for (i = 1; i <= num_formats; i++)
427
 
    {
428
 
      memset (pfd, 0, sizeof (*pfd));
429
 
 
430
 
      if (DescribePixelFormat (dc, i, sizeof (best_pfd), pfd)
431
 
          /* Check whether this format is useable by Clutter */
432
 
          && ((pfd->dwFlags & (PFD_SUPPORT_OPENGL
433
 
                               | PFD_DRAW_TO_WINDOW
434
 
                               | PFD_DOUBLEBUFFER
435
 
                               | PFD_GENERIC_FORMAT))
436
 
              == (PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW))
437
 
          && pfd->iPixelType == PFD_TYPE_RGBA
438
 
          && pfd->cColorBits >= 16 && pfd->cColorBits <= 32
439
 
          && pfd->cDepthBits >= 16 && pfd->cDepthBits <= 32
440
 
          /* Check whether this is a better format than one we've
441
 
             already found */
442
 
          && (best_pf == 0
443
 
              || clutter_stage_win32_pixel_format_is_better (&best_pfd, pfd)))
444
 
        {
445
 
          best_pf = i;
446
 
          best_pfd = *pfd;
447
 
        }
448
 
    }
449
 
 
450
 
  *pfd = best_pfd;
451
 
 
452
 
  return best_pf;
453
 
}
454
 
 
455
 
static void
456
 
clutter_stage_win32_realize (ClutterActor *actor)
457
 
{
458
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor);
 
389
clutter_stage_win32_realize (ClutterStageWindow *stage_window)
 
390
{
 
391
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
459
392
  ClutterBackendWin32 *backend_win32;
460
393
  PIXELFORMATDESCRIPTOR pfd;
461
394
  int pf;
 
395
  GError *error = NULL;
462
396
 
463
397
  CLUTTER_NOTE (MISC, "Realizing main stage");
464
398
 
470
404
      int win_xpos, win_ypos, win_width, win_height;
471
405
 
472
406
      if (window_class == 0)
473
 
        {
 
407
        {
474
408
          g_critical ("Unable to register window class");
475
 
          goto fail;
476
 
        }
 
409
          goto fail;
 
410
        }
477
411
 
478
412
      /* If we're in fullscreen mode then use the fullscreen rect
479
 
         instead */
 
413
         instead */
480
414
      if ((stage_win32->state & CLUTTER_STAGE_STATE_FULLSCREEN))
481
 
        {
482
 
          get_fullscreen_rect (stage_win32);
483
 
          win_xpos = stage_win32->fullscreen_rect.left;
484
 
          win_ypos = stage_win32->fullscreen_rect.top;
485
 
          win_width = stage_win32->fullscreen_rect.right - win_xpos;
486
 
          win_height = stage_win32->fullscreen_rect.left - win_ypos;
487
 
        }
 
415
        {
 
416
          get_fullscreen_rect (stage_win32);
 
417
          win_xpos = stage_win32->fullscreen_rect.left;
 
418
          win_ypos = stage_win32->fullscreen_rect.top;
 
419
          win_width = stage_win32->fullscreen_rect.right - win_xpos;
 
420
          win_height = stage_win32->fullscreen_rect.bottom - win_ypos;
 
421
        }
488
422
      else
489
 
        {
490
 
          win_xpos = win_ypos = CW_USEDEFAULT;
491
 
 
492
 
          get_full_window_size (stage_win32,
493
 
                                stage_win32->win_width,
494
 
                                stage_win32->win_height,
495
 
                                &win_width, &win_height);
496
 
        }
 
423
        {
 
424
          win_xpos = win_ypos = CW_USEDEFAULT;
 
425
 
 
426
          get_full_window_size (stage_win32,
 
427
                                stage_win32->win_width,
 
428
                                stage_win32->win_height,
 
429
                                &win_width, &win_height);
 
430
        }
 
431
 
 
432
      if (stage_win32->wtitle == NULL)
 
433
        stage_win32->wtitle = g_utf8_to_utf16 (".", -1, NULL, NULL, NULL);
497
434
 
498
435
      stage_win32->hwnd = CreateWindowW ((LPWSTR) MAKEINTATOM (window_class),
499
 
                                         L".",
 
436
                                         stage_win32->wtitle,
500
437
                                         get_window_style (stage_win32),
501
438
                                         win_xpos,
502
439
                                         win_ypos,
507
444
                                         NULL);
508
445
 
509
446
      if (stage_win32->hwnd == NULL)
510
 
        {
511
 
          g_critical ("Unable to create stage window");
512
 
          goto fail;
513
 
        }
 
447
        {
 
448
          g_critical ("Unable to create stage window");
 
449
          goto fail;
 
450
        }
514
451
 
515
452
      /* Store a pointer to the actor in the extra bytes of the window
516
 
         so we can quickly access it in the window procedure */
 
453
         so we can quickly access it in the window procedure */
517
454
      SetWindowLongPtrW (stage_win32->hwnd, 0, (LONG_PTR) stage_win32);
518
455
    }
519
456
 
522
459
 
523
460
  stage_win32->client_dc = GetDC (stage_win32->hwnd);
524
461
 
525
 
  pf = clutter_stage_win32_choose_pixel_format (stage_win32->client_dc, &pfd);
526
 
  
527
 
  if (pf == 0 || !SetPixelFormat (stage_win32->client_dc, pf, &pfd))
 
462
  /* Create a context. This will be a no-op if we already have one */
 
463
  if (!_clutter_backend_create_context (CLUTTER_BACKEND (backend_win32),
 
464
                                        &error))
 
465
    {
 
466
      g_critical ("Unable to realize stage: %s", error->message);
 
467
      g_error_free (error);
 
468
      goto fail;
 
469
    }
 
470
 
 
471
  /* Use the same pixel format as the dummy DC */
 
472
  pf = GetPixelFormat (backend_win32->dummy_dc);
 
473
  DescribePixelFormat (backend_win32->dummy_dc, pf, sizeof (pfd), &pfd);
 
474
  if (!SetPixelFormat (stage_win32->client_dc, pf, &pfd))
528
475
    {
529
476
      g_critical ("Unable to find suitable GL pixel format");
530
477
      goto fail;
531
478
    }
532
479
 
533
 
  if (backend_win32->gl_context == NULL)
534
 
    {
535
 
      backend_win32->gl_context = wglCreateContext (stage_win32->client_dc);
536
 
      
537
 
      if (backend_win32->gl_context == NULL)
538
 
        {
539
 
          g_critical ("Unable to create suitable GL context");
540
 
          goto fail;
541
 
        }
542
 
 
543
 
      /* Make the context current so we can check the GL version */
544
 
      wglMakeCurrent (stage_win32->client_dc, backend_win32->gl_context);
545
 
 
546
 
      if (!clutter_stage_win32_check_gl_version ())
547
 
        {
548
 
          g_critical ("OpenGL version number is too low");
549
 
          goto fail;
550
 
        }
551
 
    }
552
 
 
553
480
  CLUTTER_NOTE (BACKEND, "Successfully realized stage");
554
481
 
555
 
  return;
 
482
  return TRUE;
556
483
 
557
484
 fail:
558
 
  CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
 
485
  return FALSE;
559
486
}
560
487
 
561
488
static void
562
 
clutter_stage_win32_unrealize (ClutterActor *actor)
 
489
clutter_stage_win32_unprepare_window (ClutterStageWin32 *stage_win32)
563
490
{
564
 
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (actor);
565
 
 
566
 
  CLUTTER_NOTE (BACKEND, "Unrealizing stage");
567
 
 
568
 
  if (CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)->unrealize != NULL)
569
 
    CLUTTER_ACTOR_CLASS (clutter_stage_win32_parent_class)->unrealize (actor);
570
 
 
571
491
  if (stage_win32->client_dc)
572
492
    {
573
493
      ReleaseDC (stage_win32->hwnd, stage_win32->client_dc);
577
497
  if (!stage_win32->is_foreign_win && stage_win32->hwnd)
578
498
    {
579
499
      /* Drop the pointer to this stage in the window so that any
580
 
         further messages won't be processed. The stage might be being
581
 
         destroyed so otherwise the messages would be handled with an
582
 
         invalid stage instance */
 
500
         further messages won't be processed. The stage might be being
 
501
         destroyed so otherwise the messages would be handled with an
 
502
         invalid stage instance */
583
503
      SetWindowLongPtrW (stage_win32->hwnd, 0, (LONG_PTR) 0);
584
504
      DestroyWindow (stage_win32->hwnd);
585
 
      stage_win32->hwnd = NULL;
586
505
    }
587
506
}
588
507
 
589
508
static void
 
509
clutter_stage_win32_unrealize (ClutterStageWindow *stage_window)
 
510
{
 
511
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window);
 
512
 
 
513
  CLUTTER_NOTE (BACKEND, "Unrealizing stage");
 
514
 
 
515
  clutter_stage_win32_unprepare_window (stage_win32);
 
516
}
 
517
 
 
518
static void
590
519
clutter_stage_win32_dispose (GObject *gobject)
591
520
{
592
521
  ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (gobject);
593
522
 
 
523
  /* Make sure that context and window are destroyed in case unrealize
 
524
   * hasn't been called yet.
 
525
   */
 
526
  if (stage_win32->hwnd)
 
527
    clutter_stage_win32_unprepare_window (stage_win32);
 
528
 
 
529
  if (stage_win32->wtitle)
 
530
    g_free (stage_win32->wtitle);
 
531
 
594
532
  G_OBJECT_CLASS (clutter_stage_win32_parent_class)->dispose (gobject);
595
533
}
596
534
 
598
536
clutter_stage_win32_class_init (ClutterStageWin32Class *klass)
599
537
{
600
538
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
601
 
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
602
539
 
603
540
  gobject_class->dispose = clutter_stage_win32_dispose;
604
 
  
605
 
  actor_class->get_preferred_width = clutter_stage_win32_get_preferred_width;
606
 
  actor_class->get_preferred_height = clutter_stage_win32_get_preferred_height;
607
 
  actor_class->allocate = clutter_stage_win32_allocate;
608
 
  actor_class->realize = clutter_stage_win32_realize;
609
 
  actor_class->unrealize = clutter_stage_win32_unrealize;
610
541
}
611
542
 
612
543
static void
619
550
  stage->backend = NULL;
620
551
  stage->scroll_pos = 0;
621
552
  stage->is_foreign_win = FALSE;
622
 
 
 
553
  stage->wtitle = NULL;
 
554
  stage->is_cursor_visible = TRUE;
623
555
  stage->wrapper = NULL;
624
556
         
625
557
  CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IS_TOPLEVEL);
631
563
  iface->get_wrapper = clutter_stage_win32_get_wrapper;
632
564
  iface->set_title = clutter_stage_win32_set_title;
633
565
  iface->set_fullscreen = clutter_stage_win32_set_fullscreen;
 
566
  iface->set_cursor_visible = clutter_stage_win32_set_cursor_visible;
634
567
  iface->set_user_resizable = clutter_stage_win32_set_user_resize;
635
568
  iface->show = clutter_stage_win32_show;
636
569
  iface->hide = clutter_stage_win32_hide;
 
570
  iface->resize = clutter_stage_win32_resize;
 
571
  iface->get_geometry = clutter_stage_win32_get_geometry;
 
572
  iface->realize = clutter_stage_win32_realize;
 
573
  iface->unrealize = clutter_stage_win32_unrealize;
637
574
}
638
575
 
639
576
/**
706
643
 
707
644
  return NULL;
708
645
}
709
 
         
 
646
 
710
647
/**
711
648
 * clutter_win32_set_stage_foreign:
712
649
 * @stage: a #ClutterStage
773
710
void
774
711
clutter_stage_win32_map (ClutterStageWin32 *stage_win32)
775
712
{
776
 
  clutter_actor_map (CLUTTER_ACTOR (stage_win32));
777
713
  clutter_actor_map (CLUTTER_ACTOR (stage_win32->wrapper));
778
714
 
779
715
  clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_win32->wrapper));
782
718
void
783
719
clutter_stage_win32_unmap (ClutterStageWin32 *stage_win32)
784
720
{
785
 
  clutter_actor_unmap (CLUTTER_ACTOR (stage_win32));
786
721
  clutter_actor_unmap (CLUTTER_ACTOR (stage_win32->wrapper));
787
722
}