/*****************************************************************
 *		SetFocus  (USER32.@)
 */
HWND WINAPI SetFocus( HWND hwnd )
{
    HWND hwndTop = hwnd;
    HWND previous = GetFocus();

    TRACE( "%p prev %p\n", hwnd, previous );

    if (hwnd)
    {
        /* Check if we can set the focus to this window */
        hwnd = WIN_GetFullHandle( hwnd );
        if (!IsWindow( hwnd ))
        {
            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
            return 0;
        }
        if (hwnd == previous) return previous;  /* nothing to do */
        for (;;)
        {
            HWND parent;
            LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
            if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
            if (!(style & WS_CHILD)) break;
            parent = GetAncestor( hwndTop, GA_PARENT );
            if (!parent || parent == GetDesktopWindow())
            {
                if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return 0;
                break;
            }
            if (parent == get_hwnd_message_parent()) return 0;
            hwndTop = parent;
        }

        /* call hooks */
        if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, TRUE )) return 0;

        /* activate hwndTop if needed. */
        if (hwndTop != GetActiveWindow())
        {
            if (!set_active_window( hwndTop, NULL, FALSE, FALSE )) return 0;
            if (!IsWindow( hwnd )) return 0;  /* Abort if window destroyed */

            /* Do not change focus if the window is no longer active */
            if (hwndTop != GetActiveWindow()) return 0;
        }
    }
    else /* NULL hwnd passed in */
    {
        if (!previous) return 0;  /* nothing to do */
        if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)previous, TRUE )) return 0;
    }

    /* change focus and send messages */
    return set_focus_window( hwnd );
}
예제 #2
0
파일: focus.c 프로젝트: fvwmorg/fvwm
static Bool __try_other_screen_focus(const FvwmWindow *fw)
{
	if (fw == NULL && !Scr.flags.is_pointer_on_this_screen)
	{
		FvwmWindow *sf;

		sf = get_focus_window();
		set_focus_window(NULL);
		if (sf != NULL)
		{
			focus_grab_buttons(sf);
		}
		/* DV (25-Nov-2000): Don't give the Scr.NoFocusWin the focus
		 * here. This would steal the focus from the other screen's
		 * root window again. */
		return True;
	}

	return False;
}
/*******************************************************************
 *		set_active_window
 */
static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
{
    HWND previous = GetActiveWindow();
    BOOL ret;
    DWORD old_thread, new_thread;
    CBTACTIVATESTRUCT cbt;

    if (previous == hwnd)
    {
        if (prev) *prev = hwnd;
        return TRUE;
    }

    /* call CBT hook chain */
    cbt.fMouse     = mouse;
    cbt.hWndActive = previous;
    if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE;

    if (IsWindow(previous))
    {
        SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
        SendMessageW( previous, WM_ACTIVATE,
                      MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
    }

    SERVER_START_REQ( set_active_window )
    {
        req->handle = wine_server_user_handle( hwnd );
        if ((ret = !wine_server_call_err( req )))
            previous = wine_server_ptr_handle( reply->previous );
    }
    SERVER_END_REQ;
    if (!ret) return FALSE;
    if (prev) *prev = previous;
    if (previous == hwnd) return TRUE;

    if (hwnd)
    {
        /* send palette messages */
        if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
            SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
                                 SMTO_ABORTIFHUNG, 2000, NULL );
        if (!IsWindow(hwnd)) return FALSE;
    }

    old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0;
    new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0;

    if (old_thread != new_thread)
    {
        HWND *list, *phwnd;

        if ((list = WIN_ListChildren( GetDesktopWindow() )))
        {
            if (old_thread)
            {
                for (phwnd = list; *phwnd; phwnd++)
                {
                    if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
                        SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
                }
            }
            if (new_thread)
            {
                for (phwnd = list; *phwnd; phwnd++)
                {
                    if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
                        SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
                }
            }
            HeapFree( GetProcessHeap(), 0, list );
        }
    }

    if (IsWindow(hwnd))
    {
        SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous );
        SendMessageW( hwnd, WM_ACTIVATE,
                      MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ),
                      (LPARAM)previous );
        if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())
            PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd );

        if (hwnd == GetForegroundWindow() && !IsIconic( hwnd ))
            USER_Driver->pSetActiveWindow( hwnd );
    }

    /* now change focus if necessary */
    if (focus)
    {
        GUITHREADINFO info;

        info.cbSize = sizeof(info);
        GetGUIThreadInfo( GetCurrentThreadId(), &info );
        /* Do not change focus if the window is no more active */
        if (hwnd == info.hwndActive)
        {
            if (!info.hwndFocus || !hwnd || GetAncestor( info.hwndFocus, GA_ROOT ) != hwnd)
                set_focus_window( hwnd );
        }
    }

    return TRUE;
}
예제 #4
0
/********************************************************************
 *
 * Sets the input focus to the indicated window.
 *
 **********************************************************************/
static void DoSetFocus(Window w, FvwmWindow *Fw, Bool FocusByMouse, Bool NoWarp)
{
  extern Time lastTimestamp;
  FvwmWindow *sf;

  if (Fw && WM_TAKES_FOCUS(Fw))
  {
    send_clientmessage(dpy, w, _XA_WM_TAKE_FOCUS, lastTimestamp);
  }
  if (Fw && HAS_NEVER_FOCUS(Fw))
  {
    if (WM_TAKES_FOCUS(Fw))
    {
      /* give it a chance to take the focus itself */
      XSync(dpy, 0);
    }
    else
    {
      /* make sure the window is not hilighted */
      DrawDecorations(Fw, DRAW_ALL, False, False, None);
    }
    return;
  }
  if (Fw && !IS_LENIENT(Fw) &&
      Fw->wmhints && (Fw->wmhints->flags & InputHint) && !Fw->wmhints->input &&
      (sf = get_focus_window()) && sf->Desk == Scr.CurrentDesk)
  {
    return;
  }
  /* ClickToFocus focus queue manipulation - only performed for
   * Focus-by-mouse type focus events */
  /* Watch out: Fw may not be on the windowlist and the windowlist may be
   * empty */
  if (Fw && Fw != get_focus_window() && Fw != &Scr.FvwmRoot &&
      !IS_SCHEDULED_FOR_DESTROY(Fw))
  {
    if (FocusByMouse) /* pluck window from list and deposit at top */
    {
      /* remove Fw from list */
      if (Fw->prev)
	Fw->prev->next = Fw->next;
      if (Fw->next)
	Fw->next->prev = Fw->prev;

      /* insert Fw at start */
      Fw->next = Scr.FvwmRoot.next;
      if (Scr.FvwmRoot.next)
	Scr.FvwmRoot.next->prev = Fw;
      Scr.FvwmRoot.next = Fw;
      Fw->prev = &Scr.FvwmRoot;
    }
    else
    {
      /* move the windowlist around so that Fw is at the top */
      FvwmWindow *tmp_win;

      /* find the window on the windowlist */
      tmp_win = &Scr.FvwmRoot;
      while (tmp_win && tmp_win != Fw)
        tmp_win = tmp_win->next;

      if (tmp_win) /* the window is on the (non-zero length) windowlist */
      {
        /* make tmp_win point to the last window on the list */
        while (tmp_win->next)
          tmp_win = tmp_win->next;

        /* close the ends of the windowlist */
        tmp_win->next = Scr.FvwmRoot.next;
        Scr.FvwmRoot.next->prev = tmp_win;

        /* make Fw the new start of the list */
        Scr.FvwmRoot.next = Fw;
        /* open the closed loop windowlist */
        Fw->prev->next = NULL;
        Fw->prev = &Scr.FvwmRoot;
      }
    }
  }
  lastFocusType = FocusByMouse;

  if (!Fw && !Scr.flags.is_pointer_on_this_screen)
  {
    focus_grab_buttons(Scr.Ungrabbed, False);
    set_focus_window(NULL);
    /* DV (25-Nov-2000): Don't give the Scr.NoFocusWin the focus here. This
     * would steal the focus from the other screen's root window again. */
    /* FOCUS_SET(Scr.NoFocusWin); */
    return;
  }

  if (Fw && !NoWarp)
  {
    if (IS_ICONIFIED(Fw))
    {
      rectangle r;

      r.x = Fw->icon_g.x;
      r.y = Fw->icon_g.y;
      r.width = Fw->icon_g.width;
      r.height = Fw->icon_p_height + Fw->icon_g.height;
      if (!IsRectangleOnThisPage(&r, Fw->Desk))
      {
        Fw = NULL;
        w = Scr.NoFocusWin;
      }
    }
    else if (!IsRectangleOnThisPage(&(Fw->frame_g),Fw->Desk))
    {
      Fw = NULL;
      w = Scr.NoFocusWin;
    }
  }

  /*
      RBW - 1999/12/08 - we have to re-grab the unfocused window here for the
      MouseFocusClickRaises case also, but we can't ungrab the newly focused
      window here, or we'll never catch the raise click. For this special case,
      the newly-focused window is ungrabbed in events.c (HandleButtonPress).
  */
  if (Scr.Ungrabbed != Fw)
  {
    /* need to grab all buttons for window that we are about to unfocus */
    focus_grab_buttons(Scr.Ungrabbed, False);
  }
  /* if we do click to focus, remove the grab on mouse events that
   * was made to detect the focus change */
  if (Fw && HAS_CLICK_FOCUS(Fw))
  {
    focus_grab_buttons(Fw, True);
  }
  /* RBW - allow focus to go to a NoIconTitle icon window so
   * auto-raise will work on it... */
  if (Fw && IS_ICONIFIED(Fw))
  {
    Bool is_window_selected = False;

    if (Fw->icon_w)
    {
      w = Fw->icon_w;
      is_window_selected = True;
    }
    if ((!is_window_selected || WAS_ICON_HINT_PROVIDED(Fw)) &&
	Fw->icon_pixmap_w)
    {
      w = Fw->icon_pixmap_w;
    }
  }

  if (Fw && IS_LENIENT(Fw))
  {
    FOCUS_SET(w);
    set_focus_window(Fw);
    SET_FOCUS_CHANGE_BROADCAST_PENDING(Fw, 1);
    Scr.UnknownWinFocused = None;
  }
  else if (!Fw || !(Fw->wmhints) || !(Fw->wmhints->flags & InputHint) ||
           Fw->wmhints->input != False)
  {
    /* Window will accept input focus */
    FOCUS_SET(w);
    set_focus_window(Fw);
    if (Fw)
    {
      SET_FOCUS_CHANGE_BROADCAST_PENDING(Fw, 1);
    }
    Scr.UnknownWinFocused = None;
  }
  else if ((sf = get_focus_window()) && sf->Desk == Scr.CurrentDesk)
  {
    /* Window doesn't want focus. Leave focus alone */
    /* FOCUS_SET(Scr.Hilite->w);*/
  }
  else
  {
    FOCUS_SET(Scr.NoFocusWin);
    set_focus_window(NULL);
  }
  XSync(dpy,0);

  return;
}
예제 #5
0
파일: focus.c 프로젝트: fvwmorg/fvwm
/*
 * Sets the input focus to the indicated window.
 */
static void __set_focus_to_fwin(
	Window w, FvwmWindow *fw, sftfwin_args_t *args)
{
	FvwmWindow *sf;

	if (__try_forbid_user_focus(w, fw) == True)
	{
		return;
	}
	__try_program_focus(w, fw);
	if (__check_allow_focus(w, fw, args->set_by) == False)
	{
		return;
	}
	__update_windowlist(fw, args->set_by, args->is_focus_by_flip_focus_cmd);
	if (__try_other_screen_focus(fw) == True)
	{
		return;
	}

	if (fw && !args->do_forbid_warp)
	{
		if (IS_ICONIFIED(fw))
		{
			rectangle r;
			Bool rc;

			rc = get_visible_icon_geometry(fw, &r);
			if (!rc || !IsRectangleOnThisPage(&r, fw->Desk))
			{
				fw = NULL;
				w = Scr.NoFocusWin;
			}
		}
		else if (!IsRectangleOnThisPage(&(fw->g.frame), fw->Desk))
		{
			fw = NULL;
			w = Scr.NoFocusWin;
		}
	}

	sf = get_focus_window();
	if (fw == NULL)
	{
		FOCUS_SET(Scr.NoFocusWin, NULL);
		set_focus_window(NULL);
		Scr.UnknownWinFocused = None;
		XFlush(dpy);
		return;
	}
	/* RBW - allow focus to go to a NoIconTitle icon window so
	 * auto-raise will work on it. */
	if (IS_ICONIFIED(fw))
	{
		Bool is_window_selected = False;

		if (FW_W_ICON_TITLE(fw))
		{
			w = FW_W_ICON_TITLE(fw);
			is_window_selected = True;
		}
		if ((!is_window_selected || WAS_ICON_HINT_PROVIDED(fw)) &&
		    FW_W_ICON_PIXMAP(fw))
		{
			w = FW_W_ICON_PIXMAP(fw);
		}
	}

	if (FP_IS_LENIENT(FW_FOCUS_POLICY(fw)))
	{
		FOCUS_SET(w, fw);
		set_focus_window(fw);
		if (args->do_allow_force_broadcast)
		{
			SET_FOCUS_CHANGE_BROADCAST_PENDING(fw, 1);
		}
		Scr.UnknownWinFocused = None;
	}
	else if (focus_does_accept_input_focus(fw))
	{
		/* Window will accept input focus */
		if (Scr.StolenFocusWin == w && Scr.UnknownWinFocused != None)
		{
			/* Without this FocusIn is not generated on the
			 * window if it was focuesed when the unmanaged
			 * window took focus. */
			FOCUS_SET(Scr.NoFocusWin, NULL);

		}
		FOCUS_SET(w, fw);
		set_focus_window(fw);
		if (fw)
		{
			if (args->do_allow_force_broadcast)
			{
				SET_FOCUS_CHANGE_BROADCAST_PENDING(fw, 1);
			}
		}
		Scr.UnknownWinFocused = None;
	}
	else if (sf && sf->Desk == Scr.CurrentDesk)
	{
		/* Window doesn't want focus. Leave focus alone */
	}
	else
	{
		FOCUS_SET(Scr.NoFocusWin, NULL);
		set_focus_window(NULL);
	}
	XFlush(dpy);

	return;
}