@@ -35,7 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(internat);
3535#define TIMER_LANG_CHANGED_DELAY 200
3636
3737FN_KbSwitchSetHooks KbSwitchSetHooks = NULL ;
38- UINT ShellHookMessage = 0 ;
3938
4039HINSTANCE g_hInst = NULL ;
4140HMODULE g_hHookDLL = NULL ;
@@ -44,6 +43,9 @@ HICON g_hTrayIcon = NULL;
4443HWND g_hwndLastActive = NULL ;
4544INT g_cKLs = 0 ;
4645HKL g_ahKLs [64 ];
46+ HMENU g_hPopupMenu = NULL ;
47+ UINT g_uTaskbarRestartMsg = 0 ;
48+ UINT g_uShellHookMessage = 0 ;
4749
4850/* Debug logging */
4951ULONG NTAPI
@@ -682,185 +684,213 @@ static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
682684 return TRUE;
683685}
684686
685- LRESULT CALLBACK
686- WndProc (HWND hwnd , UINT Message , WPARAM wParam , LPARAM lParam )
687+ // WM_CREATE
688+ static INT
689+ KbSwitch_OnCreate (HWND hwnd )
687690{
688- static HMENU s_hMenu = NULL , s_hRightPopupMenu = NULL ;
689- static UINT s_uTaskbarRestart ;
690- POINT pt ;
691- HMENU hLeftPopupMenu ;
691+ if (!SetHooks ())
692+ {
693+ MessageBox (NULL , TEXT ("SetHooks failed." ), NULL , MB_ICONERROR );
694+ return -1 ; /* Failed */
695+ }
696+
697+ LoadSpecialIds ();
698+
699+ UpdateLayoutList (NULL );
700+ AddTrayIcon (hwnd );
701+
702+ ActivateLayout (hwnd , g_nCurrentLayoutNum , NULL , TRUE);
703+ g_uTaskbarRestartMsg = RegisterWindowMessage (TEXT ("TaskbarCreated" ));
692704
693- switch (Message )
705+ return 0 ; /* Success */
706+ }
707+
708+ // WM_DESTROY
709+ static void
710+ KbSwitch_OnDestroy (HWND hwnd )
711+ {
712+ KillTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED );
713+ DeleteHooks ();
714+ if (g_hPopupMenu )
715+ DestroyMenu (g_hPopupMenu );
716+ DeleteTrayIcon (hwnd );
717+ PostQuitMessage (0 );
718+ }
719+
720+ // WM_TIMER
721+ static void
722+ KbSwitch_OnTimer (HWND hwnd , UINT_PTR nTimerID )
723+ {
724+ if (nTimerID == TIMER_ID_LANG_CHANGED_DELAYED )
694725 {
695- case WM_CREATE :
696- {
697- if (!SetHooks ())
698- {
699- MessageBox (NULL , TEXT ("SetHooks failed." ), NULL , MB_ICONERROR );
700- return -1 ;
701- }
726+ KillTimer (hwnd , nTimerID );
727+ HKL hKL = GetActiveKL ();
728+ UpdateLayoutList (hKL );
729+ UpdateLanguageDisplay (hwnd , hKL );
730+ }
731+ }
702732
703- LoadSpecialIds ();
733+ // WM_NOTIFYICONMSG
734+ static void
735+ KbSwitch_OnNotifyIconMsg (HWND hwnd , UINT uMouseMsg )
736+ {
737+ if (uMouseMsg != WM_LBUTTONUP && uMouseMsg != WM_RBUTTONUP )
738+ return ;
704739
705- UpdateLayoutList (NULL );
706- AddTrayIcon (hwnd );
740+ UpdateLayoutList (NULL );
707741
708- ActivateLayout (hwnd , g_nCurrentLayoutNum , NULL , TRUE);
709- s_uTaskbarRestart = RegisterWindowMessage (TEXT ("TaskbarCreated" ));
710- break ;
711- }
742+ POINT pt ;
743+ GetCursorPos (& pt );
712744
713- case WM_TIMER :
714- {
715- if (wParam == TIMER_ID_LANG_CHANGED_DELAYED )
716- {
717- KillTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED );
718- HKL hKL = GetActiveKL ();
719- UpdateLayoutList (hKL );
720- UpdateLanguageDisplay (hwnd , hKL );
721- }
722- break ;
723- }
745+ SetForegroundWindow (hwnd );
724746
725- // WM_LANG_CHANGED message:
726- // wParam: HWND hwndTarget or zero
727- // lParam: HKL hKL or zero
728- case WM_LANG_CHANGED : /* Comes from kbsdll.dll and this module */
729- {
730- TRACE ("WM_LANG_CHANGED: wParam:%p, lParam:%p\n" , wParam , lParam );
731- /* Delayed action */
732- KillTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED );
733- SetTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED , TIMER_LANG_CHANGED_DELAY , NULL );
747+ INT nID ;
748+ if (uMouseMsg == WM_LBUTTONUP )
749+ {
750+ /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
751+ HMENU hLeftPopupMenu = BuildLeftPopupMenu ();
752+ nID = TrackPopupMenu (hLeftPopupMenu , TPM_RETURNCMD , pt .x , pt .y , 0 , hwnd , NULL );
753+ DestroyMenu (hLeftPopupMenu );
754+ }
755+ else /* WM_RBUTTONUP */
756+ {
757+ if (!g_hPopupMenu )
758+ g_hPopupMenu = LoadMenu (g_hInst , MAKEINTRESOURCE (IDR_POPUP ));
759+
760+ HMENU hSubMenu = GetSubMenu (g_hPopupMenu , 0 );
761+ nID = TrackPopupMenu (hSubMenu , TPM_RETURNCMD , pt .x , pt .y , 0 , hwnd , NULL );
762+ }
763+
764+ PostMessage (hwnd , WM_NULL , 0 , 0 );
765+
766+ if (nID )
767+ PostMessage (hwnd , WM_COMMAND , nID , 0 );
768+ }
769+
770+ // WM_COMMAND
771+ static void
772+ KbSwitch_OnCommand (HWND hwnd , UINT nID )
773+ {
774+ switch (nID )
775+ {
776+ case ID_EXIT :
777+ PostMessage (hwnd , WM_CLOSE , 0 , 0 );
734778 break ;
735- }
736779
737- // WM_WINDOW_ACTIVATE message:
738- // wParam: HWND hwndTarget or zero
739- // lParam: zero
740- case WM_WINDOW_ACTIVATE : /* Comes from kbsdll.dll and this module */
780+ case ID_PREFERENCES :
741781 {
742- TRACE ("WM_WINDOW_ACTIVATE: wParam:%p, lParam:%p\n" , wParam , lParam );
743- HWND hwndFore = wParam ? (HWND )wParam : GetForegroundWindow ();
744- if (RememberLastActive (hwnd , hwndFore ))
745- return UpdateLanguageDisplayCurrent (hwnd , hwndFore );
782+ INT_PTR ret = (INT_PTR )ShellExecute (hwnd , NULL ,
783+ TEXT ("control.exe" ), TEXT ("input.dll" ),
784+ NULL , SW_SHOWNORMAL );
785+ if (ret <= 32 )
786+ MessageBox (hwnd , _T ("Can't start input.dll" ), NULL , MB_ICONERROR );
746787 break ;
747788 }
748789
749- case WM_NOTIFYICONMSG :
790+ default :
750791 {
751- switch ( lParam )
792+ if ( 1 <= nID && nID <= 1000 )
752793 {
753- case WM_RBUTTONUP :
754- case WM_LBUTTONUP :
794+ if (!IsWindow (g_hwndLastActive ))
755795 {
756- UpdateLayoutList (NULL );
757-
758- GetCursorPos (& pt );
759- SetForegroundWindow (hwnd );
760-
761- INT nID ;
762- if (lParam == WM_LBUTTONUP )
763- {
764- /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
765- hLeftPopupMenu = BuildLeftPopupMenu ();
766- nID = TrackPopupMenu (hLeftPopupMenu , TPM_RETURNCMD , pt .x , pt .y , 0 , hwnd , NULL );
767- DestroyMenu (hLeftPopupMenu );
768- }
769- else
770- {
771- if (!s_hRightPopupMenu )
772- {
773- s_hMenu = LoadMenu (g_hInst , MAKEINTRESOURCE (IDR_POPUP ));
774- s_hRightPopupMenu = GetSubMenu (s_hMenu , 0 );
775- }
776- nID = TrackPopupMenu (s_hRightPopupMenu , TPM_RETURNCMD , pt .x , pt .y , 0 , hwnd , NULL );
777- }
778-
779- PostMessage (hwnd , WM_NULL , 0 , 0 );
780-
781- if (nID )
782- PostMessage (hwnd , WM_COMMAND , nID , 0 );
783-
784- break ;
796+ g_hwndLastActive = NULL ;
785797 }
798+ ActivateLayout (hwnd , nID , g_hwndLastActive , FALSE);
786799 }
787800 break ;
788801 }
802+ }
803+ }
789804
790- case WM_COMMAND :
791- switch (LOWORD (wParam ))
792- {
793- case ID_EXIT :
794- {
795- PostMessage (hwnd , WM_CLOSE , 0 , 0 );
796- break ;
797- }
805+ // WM_LANG_CHANGED
806+ static LRESULT
807+ KbSwitch_OnLangChanged (HWND hwnd , HWND hwndTarget OPTIONAL , HKL hKL OPTIONAL )
808+ {
809+ TRACE ("WM_LANG_CHANGED: hwndTarget:%p, hKL:%p\n" , hwndTarget , hKL );
810+ /* Delayed action */
811+ KillTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED );
812+ SetTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED , TIMER_LANG_CHANGED_DELAY , NULL );
813+ return 0 ;
814+ }
798815
799- case ID_PREFERENCES :
800- {
801- INT_PTR ret = (INT_PTR )ShellExecute (hwnd , NULL ,
802- TEXT ("control.exe" ), TEXT ("input.dll" ),
803- NULL , SW_SHOWNORMAL );
804- if (ret <= 32 )
805- MessageBox (hwnd , _T ("Can't start input.dll" ), NULL , MB_ICONERROR );
806- break ;
807- }
816+ // WM_WINDOW_ACTIVATE
817+ static LRESULT
818+ KbSwitch_OnWindowActivate (HWND hwnd , HWND hwndTarget OPTIONAL , LPARAM lParam OPTIONAL )
819+ {
820+ TRACE ("WM_WINDOW_ACTIVATE: hwndTarget:%p, lParam:%p\n" , hwndTarget , lParam );
821+ HWND hwndFore = hwndTarget ? hwndTarget : GetForegroundWindow ();
822+ if (RememberLastActive (hwnd , hwndFore ))
823+ return UpdateLanguageDisplayCurrent (hwnd , hwndFore );
824+ return 0 ;
825+ }
808826
809- default :
810- {
811- if (1 <= LOWORD (wParam ) && LOWORD (wParam ) <= 1000 )
812- {
813- if (!IsWindow (g_hwndLastActive ))
814- {
815- g_hwndLastActive = NULL ;
816- }
817- ActivateLayout (hwnd , LOWORD (wParam ), g_hwndLastActive , FALSE);
818- }
819- break ;
820- }
821- }
827+ // WM_SETTINGCHANGE
828+ static void
829+ KbSwitch_OnSettingChange (HWND hwnd , WPARAM wParam , LPARAM lParam )
830+ {
831+ if (wParam == SPI_SETNONCLIENTMETRICS )
832+ PostMessage (hwnd , WM_WINDOW_ACTIVATE , 0 , 0 );
833+ }
834+
835+ static LRESULT
836+ KbSwitch_OnDefault (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
837+ {
838+ if (uMsg == g_uTaskbarRestartMsg )
839+ {
840+ UpdateLayoutList (NULL );
841+ AddTrayIcon (hwnd );
842+ return 0 ;
843+ }
844+
845+ if (uMsg == g_uShellHookMessage )
846+ {
847+ TRACE ("g_uShellHookMessage: wParam:%p, lParam:%p\n" , wParam , lParam );
848+ if (wParam == HSHELL_LANGUAGE )
849+ PostMessage (hwnd , WM_LANG_CHANGED , 0 , 0 );
850+ else if (wParam == HSHELL_WINDOWACTIVATED || wParam == HSHELL_RUDEAPPACTIVATED )
851+ PostMessage (hwnd , WM_WINDOW_ACTIVATE , 0 , 0 );
852+ return 0 ;
853+ }
854+
855+ return DefWindowProc (hwnd , uMsg , wParam , lParam );
856+ }
857+
858+ LRESULT CALLBACK
859+ WndProc (HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
860+ {
861+ switch (uMsg )
862+ {
863+ case WM_CREATE :
864+ return KbSwitch_OnCreate (hwnd );
865+
866+ case WM_TIMER :
867+ KbSwitch_OnTimer (hwnd , (UINT_PTR )wParam );
868+ break ;
869+
870+ case WM_LANG_CHANGED : /* Comes from kbsdll.dll and this module */
871+ return KbSwitch_OnLangChanged (hwnd , (HWND )wParam , (HKL )lParam );
872+
873+ case WM_WINDOW_ACTIVATE : /* Comes from kbsdll.dll and this module */
874+ return KbSwitch_OnWindowActivate (hwnd , (HWND )wParam , lParam );
875+
876+ case WM_NOTIFYICONMSG :
877+ KbSwitch_OnNotifyIconMsg (hwnd , (UINT )lParam );
878+ break ;
879+
880+ case WM_COMMAND :
881+ KbSwitch_OnCommand (hwnd , LOWORD (wParam ));
822882 break ;
823883
824884 case WM_SETTINGCHANGE :
825- {
826- if (wParam == SPI_SETNONCLIENTMETRICS )
827- {
828- PostMessage (hwnd , WM_WINDOW_ACTIVATE , 0 , 0 );
829- break ;
830- }
831- }
832- break ;
885+ KbSwitch_OnSettingChange (hwnd , wParam , lParam );
886+ break ;
833887
834888 case WM_DESTROY :
835- {
836- KillTimer (hwnd , TIMER_ID_LANG_CHANGED_DELAYED );
837- DeleteHooks ();
838- DestroyMenu (s_hMenu );
839- DeleteTrayIcon (hwnd );
840- PostQuitMessage (0 );
889+ KbSwitch_OnDestroy (hwnd );
841890 break ;
842- }
843891
844892 default :
845- {
846- if (Message == s_uTaskbarRestart )
847- {
848- UpdateLayoutList (NULL );
849- AddTrayIcon (hwnd );
850- break ;
851- }
852- else if (Message == ShellHookMessage )
853- {
854- TRACE ("ShellHookMessage: wParam:%p, lParam:%p\n" , wParam , lParam );
855- if (wParam == HSHELL_LANGUAGE )
856- PostMessage (hwnd , WM_LANG_CHANGED , 0 , 0 );
857- else if (wParam == HSHELL_WINDOWACTIVATED || wParam == HSHELL_RUDEAPPACTIVATED )
858- PostMessage (hwnd , WM_WINDOW_ACTIVATE , 0 , 0 );
859-
860- break ;
861- }
862- return DefWindowProc (hwnd , Message , wParam , lParam );
863- }
893+ return KbSwitch_OnDefault (hwnd , uMsg , wParam , lParam );
864894 }
865895
866896 return 0 ;
@@ -912,7 +942,7 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdSh
912942 }
913943
914944 hwnd = CreateWindow (szKbSwitcherName , NULL , 0 , 0 , 0 , 1 , 1 , HWND_DESKTOP , NULL , hInstance , NULL );
915- ShellHookMessage = RegisterWindowMessage (L"SHELLHOOK" );
945+ g_uShellHookMessage = RegisterWindowMessage (L"SHELLHOOK" );
916946 if (!RegisterShellHookWindow (hwnd ))
917947 {
918948 ERR ("RegisterShellHookWindow failed\n" );
0 commit comments