freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2-demos] master 8d421a4 1/2: [graph/win32] Implement smooth res


From: Werner Lemberg
Subject: [freetype2-demos] master 8d421a4 1/2: [graph/win32] Implement smooth resizing.
Date: Fri, 31 Dec 2021 14:02:34 -0500 (EST)

branch: master
commit 8d421a4cec1f6e0fa23b535f9c6553a77c6738c4
Author: Alexei Podtelezhnikov <apodtele@gmail.com>
Commit: Alexei Podtelezhnikov <apodtele@gmail.com>

    [graph/win32] Implement smooth resizing.
    
    The window creation and the message loop has to be put in a separate
    thread in order to achieve smooth resizing.  Othrewise, the modal
    loop cannot be interrupted to redraw the canvas.  The main thread
    also has a loop to receive the reposted messages, to update the
    canvas and send WM_PAINT back via UpdateWindow.  After this update
    the win32 resizing feels similar to the X11 resizing.
    
    * graph/win32/grwin32.c (grWin32Surface): Store the host thread id.
    (gr_win32_surface_init): Spin off `CreateWindow` from here...
    (Window_ThreadProc): ... to here and run the window message loop.
    (Message_Process): Updated to repost messages to the host thread.
    (gr_win32_surface_listen_event): Run the host thread message loop.
---
 graph/win32/grwin32.c | 107 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 70 insertions(+), 37 deletions(-)

diff --git a/graph/win32/grwin32.c b/graph/win32/grwin32.c
index 18b3e2b..7222015 100644
--- a/graph/win32/grwin32.c
+++ b/graph/win32/grwin32.c
@@ -57,6 +57,7 @@
 #endif
 
 /*  Custom messages. */
+#define WM_STATUS  WM_USER+512
 #define WM_RESIZE  WM_USER+517
 
 
@@ -99,6 +100,7 @@
   typedef struct grWin32SurfaceRec_
   {
     grSurface     root;
+    DWORD         host;
     HWND          window;
     HICON         sIcon;
     HICON         bIcon;
@@ -305,8 +307,6 @@ gr_win32_surface_set_icon( grWin32Surface*  surface,
     return 0;
   case ICON_BIG:
     surface->bIcon = hIcon;
-    SetClassLongPtr( surface->window, GCLP_HBRBACKGROUND,
-                     (LONG_PTR)CreatePatternBrush( ici.hbmColor ) );
     return s[0];
   default:
     return 0;  /* should not happen */
@@ -373,7 +373,7 @@ gr_win32_surface_listen_event( grWin32Surface*  surface,
 
   event_mask=event_mask;  /* unused parameter */
 
-  while ( GetMessage( &msg, NULL, 0, 0 ) > 0 )
+  while ( GetMessage( &msg, (HWND)-1, 0, 0 ) > 0 )
   {
     switch ( msg.message )
     {
@@ -423,16 +423,61 @@ gr_win32_surface_listen_event( grWin32Surface*  surface,
       }
       break;
     }
+  }
+}
+
+
+DWORD WINAPI Window_ThreadProc( LPVOID lpParameter )
+{
+  grWin32Surface*  surface = (grWin32Surface*)lpParameter;
+  DWORD            style   = WS_OVERLAPPEDWINDOW;
+  RECT             WndRect;
+  MSG              msg;
+
+  WndRect.left   = 0;
+  WndRect.top    = 0;
+  WndRect.right  = surface->root.bitmap.width;
+  WndRect.bottom = surface->root.bitmap.rows;
+
+  AdjustWindowRect( &WndRect, style, FALSE );
+
+  surface->window = CreateWindow(
+       /* LPCSTR lpszClassName;    */ "FreeTypeTestGraphicDriver",
+       /* LPCSTR lpszWindowName;   */ "FreeType Test Graphic Driver",
+       /* DWORD dwStyle;           */  style,
+       /* int x;                   */  CW_USEDEFAULT,
+       /* int y;                   */  CW_USEDEFAULT,
+       /* int nWidth;              */  WndRect.right - WndRect.left,
+       /* int nHeight;             */  WndRect.bottom - WndRect.top,
+       /* HWND hwndParent;         */  HWND_DESKTOP,
+       /* HMENU hmenu;             */  0,
+       /* HINSTANCE hinst;         */  GetModuleHandle( NULL ),
+       /* void FAR* lpvParam;      */  surface );
+
+  PostThreadMessage( surface->host, WM_STATUS, (WPARAM)surface->window, 0 );
+
+  if ( surface->window == 0 )
+    return -1;
 
+  ShowWindow( surface->window, SW_SHOWNORMAL );
+
+  while ( GetMessage( &msg, surface->window, 0, 0 ) > 0 )
+  {
     TranslateMessage( &msg );
     DispatchMessage( &msg );
   }
+
+  LOG(("Window thread done.\n"));
+  return 0;
 }
 
+
 static grWin32Surface*
 gr_win32_surface_init( grWin32Surface*  surface,
                        grBitmap*        bitmap )
 {
+  MSG  msg;
+
   surface->root.bitmap.grays = bitmap->grays;
 
   /* Set default mode */
@@ -540,36 +585,18 @@ gr_win32_surface_init( grWin32Surface*  surface,
     return 0;         /* Unknown mode */
   }
 
-  {
-    DWORD  style = WS_OVERLAPPEDWINDOW;
-    RECT   WndRect;
-
-    WndRect.left   = 0;
-    WndRect.top    = 0;
-    WndRect.right  = bitmap->width;
-    WndRect.bottom = bitmap->rows;
-
-    AdjustWindowRect( &WndRect, style, FALSE );
-
-    surface->window = CreateWindow(
-            /* LPCSTR lpszClassName;    */ "FreeTypeTestGraphicDriver",
-            /* LPCSTR lpszWindowName;   */ "FreeType Test Graphic Driver",
-            /* DWORD dwStyle;           */  style,
-            /* int x;                   */  CW_USEDEFAULT,
-            /* int y;                   */  CW_USEDEFAULT,
-            /* int nWidth;              */  WndRect.right - WndRect.left,
-            /* int nHeight;             */  WndRect.bottom - WndRect.top,
-            /* HWND hwndParent;         */  HWND_DESKTOP,
-            /* HMENU hmenu;             */  0,
-            /* HINSTANCE hinst;         */  GetModuleHandle( NULL ),
-            /* void FAR* lpvParam;      */  surface );
-  }
+  /* set up the main message queue and spin off the window thread */
+  PeekMessage( &msg, (HWND)-1, WM_USER, WM_USER, PM_NOREMOVE );
+  surface->host = GetCurrentThreadId();
 
-  if ( surface->window == 0 )
-    return  0;
+  CreateThread( NULL, 0, Window_ThreadProc, (LPVOID)surface, 0, NULL );
 
-  ShowWindow( surface->window, SW_SHOWNORMAL );
+  /* listen if window is created */
+  if ( GetMessage ( &msg, (HWND)-1, WM_STATUS, WM_STATUS ) < 0 ||
+       !msg.wParam )
+    return 0;
 
+  /* wrap up */
   surface->root.done         = (grDoneSurfaceFunc) gr_win32_surface_done;
   surface->root.refresh_rect = (grRefreshRectFunc) 
gr_win32_surface_refresh_rectangle;
   surface->root.set_title    = (grSetTitleFunc)    gr_win32_surface_set_title;
@@ -611,15 +638,14 @@ LRESULT CALLBACK Message_Process( HWND handle, UINT mess,
     {
     case WM_CLOSE:
       /* warn the main thread to quit if it didn't know */
-      PostMessage( handle, WM_CHAR, (WPARAM)grKeyEsc, 0 );
+      PostThreadMessage( surface->host, WM_CHAR, (WPARAM)grKeyEsc, 0 );
       break;
 
     case WM_SIZE:
       if ( wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED )
-        PostMessage( handle, WM_RESIZE, wParam, lParam );
+        PostThreadMessage( surface->host, WM_RESIZE, wParam, lParam );
       break;
 
-#ifdef DEBUG
     case WM_SIZING:
       {
         PRECT  r = (PRECT)lParam;
@@ -638,21 +664,28 @@ LRESULT CALLBACK Message_Process( HWND handle, UINT mess,
               y, x, r->left, r->top, r->right, r->bottom,
               WndRect.right, WndRect.bottom ));
 
-        /* XXX: We cannot simply interrupt here and resize the image. */
+        PostThreadMessage( surface->host, WM_RESIZE, SIZE_RESTORED,
+                           MAKELPARAM( WndRect.right, WndRect.bottom ) );
       }
       break;
-#endif
 
     case WM_EXITSIZEMOVE:
       {
         RECT  WndRect;
 
         GetClientRect( handle, &WndRect );
-        PostMessage( handle, WM_RESIZE, SIZE_RESTORED,
-                     MAKELPARAM( WndRect.right, WndRect.bottom ) );
+        PostThreadMessage( surface->host, WM_RESIZE, SIZE_RESTORED,
+                           MAKELPARAM( WndRect.right, WndRect.bottom ) );
       }
       break;
 
+    case WM_KEYDOWN:
+    case WM_SYSKEYDOWN:
+    case WM_CHAR:
+      /* repost to the main thread */
+      PostThreadMessage( surface->host, mess, wParam, lParam );
+      break;
+
     case WM_PAINT:
       {
         HDC           hDC;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]