IDE & LCL: Move focus to editor after hitting breakpoint. Patch from August Klein, issue #15967

git-svn-id: trunk@31087 -
This commit is contained in:
juha 2011-06-05 06:22:54 +00:00
parent 8f85c6d37a
commit 4b57ac797b
11 changed files with 193 additions and 12 deletions

View File

@ -96,6 +96,7 @@ type
FDebugger: TDebugger; FDebugger: TDebugger;
FDialogs: array[TDebugDialogType] of TDebuggerDlg; FDialogs: array[TDebugDialogType] of TDebuggerDlg;
FPrevShownWindow: HWND; FPrevShownWindow: HWND;
FStepping: Boolean;
// keep track of the last reported location // keep track of the last reported location
FCurrentLocation: TDBGLocationRec; FCurrentLocation: TDBGLocationRec;
FIgnoreSourceFiles: TStringList; // a list of unfindable sourcefiles, that should not be prompted anymore FIgnoreSourceFiles: TStringList; // a list of unfindable sourcefiles, that should not be prompted anymore
@ -868,10 +869,10 @@ begin
if (FDebugger.State in [dsRun]) if (FDebugger.State in [dsRun])
then begin then begin
// hide IDE during run // hide IDE during run
if EnvironmentOptions.HideIDEOnRun and (MainIDE.ToolStatus=itDebugger) if EnvironmentOptions.HideIDEOnRun and (MainIDE.ToolStatus=itDebugger) and not FStepping
then MainIDE.HideIDE; then MainIDE.HideIDE;
if FPrevShownWindow <> 0 then if (FPrevShownWindow <> 0) and not FStepping then
begin begin
SetForegroundWindow(FPrevShownWindow); SetForegroundWindow(FPrevShownWindow);
FPrevShownWindow := 0; FPrevShownWindow := 0;
@ -887,12 +888,16 @@ begin
end end
else if (OldState in [dsRun]) then else if (OldState in [dsRun]) then
begin begin
if EnvironmentOptions.HideIDEOnRun if not FStepping then
then MainIDE.UnhideIDE; begin
FPrevShownWindow := GetForegroundWindow; FPrevShownWindow := GetForegroundWindow;
if EnvironmentOptions.HideIDEOnRun then
MainIDE.UnhideIDE;
if not EnvironmentOptions.SingleTaskBarButton then
Application.BringToFront; Application.BringToFront;
end; end;
end; end;
end;
// unmark execution line // unmark execution line
if (not (FDebugger.State in [dsInit, dsPause])) and (SourceEditorManager <> nil) if (not (FDebugger.State in [dsInit, dsPause])) and (SourceEditorManager <> nil)
@ -932,6 +937,7 @@ begin
FDebugger.ErrorStateInfo, ftError, [frStop]); FDebugger.ErrorStateInfo, ftError, [frStop]);
end; end;
dsStop: begin dsStop: begin
FPrevShownWindow:=0;
if (OldState<>dsIdle) if (OldState<>dsIdle)
then begin then begin
if EnvironmentOptions.DebuggerShowStopMessage if EnvironmentOptions.DebuggerShowStopMessage
@ -1956,6 +1962,7 @@ begin
Exit; Exit;
end; end;
FStepping:=True;
FDebugger.StepInto; FDebugger.StepInto;
Result := mrOk; Result := mrOk;
end; end;
@ -1970,6 +1977,7 @@ begin
Exit; Exit;
end; end;
FStepping:=True;
FDebugger.StepOver; FDebugger.StepOver;
Result := mrOk; Result := mrOk;
end; end;
@ -1984,6 +1992,7 @@ begin
Exit; Exit;
end; end;
FStepping:=True;
FDebugger.StepIntoInstr; FDebugger.StepIntoInstr;
Result := mrOk; Result := mrOk;
// Todo: move to DebuggerChangeState (requires the last run-command-type to be avail) // Todo: move to DebuggerChangeState (requires the last run-command-type to be avail)
@ -2000,6 +2009,7 @@ begin
Exit; Exit;
end; end;
FStepping:=True;
FDebugger.StepOverInstr; FDebugger.StepOverInstr;
Result := mrOk; Result := mrOk;
// Todo: move to DebuggerChangeState (requires the last run-command-type to be avail) // Todo: move to DebuggerChangeState (requires the last run-command-type to be avail)
@ -2016,6 +2026,7 @@ begin
Exit; Exit;
end; end;
FStepping:=True;
FDebugger.StepOut; FDebugger.StepOut;
Result := mrOk; Result := mrOk;
end; end;
@ -2152,6 +2163,7 @@ begin
exit; exit;
end; end;
Include(FManagerStates,dmsRunning); Include(FManagerStates,dmsRunning);
FStepping:=False;
try try
FDebugger.Run; FDebugger.Run;
finally finally

View File

@ -168,6 +168,8 @@ procedure gdk_draw_pixbuf(drawable : PGdkDrawable; gc : PGdkGC; pixbuf : PGdkPix
dither : TGdkRgbDither; x_dither, y_dither : gint); cdecl; external gdklib; dither : TGdkRgbDither; x_dither, y_dither : gint); cdecl; external gdklib;
function gdk_screen_get_default: PGdkScreen; cdecl; external gdklib; function gdk_screen_get_default: PGdkScreen; cdecl; external gdklib;
function gdk_screen_get_rgb_colormap(screen: PGdkScreen): PGdkColormap; cdecl; external gdklib; function gdk_screen_get_rgb_colormap(screen: PGdkScreen): PGdkColormap; cdecl; external gdklib;
function gdk_x11_get_default_xdisplay: pointer; cdecl; external gdklib;
function gdk_x11_get_default_root_xwindow: guint; cdecl; external gdklib;
// gdk 2.4 // gdk 2.4
function gdk_cursor_new_from_pixbuf(display: PGdkDisplay; pixbuf: PGdkPixbuf; x, y: gint): PGdkCursor; cdecl; external gdklib name 'gdk_cursor_new_from_pixbuf'; function gdk_cursor_new_from_pixbuf(display: PGdkDisplay; pixbuf: PGdkPixbuf; x, y: gint): PGdkCursor; cdecl; external gdklib name 'gdk_cursor_new_from_pixbuf';

View File

@ -298,6 +298,10 @@ type
{$I gtk2winapih.inc} {$I gtk2winapih.inc}
{$I gtk2lclintfh.inc} {$I gtk2lclintfh.inc}
public public
{$IFDEF HASX}
function X11Raise(AHandle: HWND): boolean;
function X11GetActiveWindow: HWND;
{$ENDIF}
procedure StartFocusTimer; procedure StartFocusTimer;
property AppActive: Boolean read GetAppActive write SetAppActive; property AppActive: Boolean read GetAppActive write SetAppActive;
property LastFocusIn: PGtkWidget read FLastFocusIn write FLastFocusIn; property LastFocusIn: PGtkWidget read FLastFocusIn write FLastFocusIn;

View File

@ -1156,6 +1156,8 @@ procedure TGtk2WidgetSet.AppBringToFront;
begin begin
if Assigned(Application.MainForm) and Application.MainForm.HandleAllocated then if Assigned(Application.MainForm) and Application.MainForm.HandleAllocated then
gdk_window_raise(PGtkWidget(Application.MainForm.Handle)^.window); gdk_window_raise(PGtkWidget(Application.MainForm.Handle)^.window);
gdk_window_focus(PGtkWidget(Application.MainForm.Handle)^.window,
gtk_get_current_event_time);
end; end;
procedure TGtk2WidgetSet.AppMinimize; procedure TGtk2WidgetSet.AppMinimize;
@ -4251,6 +4253,74 @@ begin
then gdk_pixmap_unref(TempMaskBitmap); then gdk_pixmap_unref(TempMaskBitmap);
end; end;
{$IFDEF HASX}
function TGtk2WidgetSet.X11Raise(AHandle: HWND): boolean;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
XClient: TXClientMessageEvent;
WMAtom: TAtom;
screen: PGdkScreen;
begin
Result:=false;
screen:=gdk_screen_get_default;
Display := gdk_x11_get_default_xdisplay;
if Display = nil then
exit;
ScreenNum := gdk_screen_get_number(screen);
RootWin := gdk_x11_get_default_root_xwindow;
XClient._type := ClientMessage;
XClient.window := AHandle;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
XClient.message_type := WMATom;
XClient.format := 32;
XClient.data.l[0] := 1;
XClient.data.l[1] := 0;
XClient.data.l[2] := 0;
Result:=XSendEvent (Display, RootWin, False,
SubstructureRedirectMask or SubstructureNotifyMask,
@XClient)<>0;
end;
function TGtk2WidgetSet.X11GetActivewindow: HWND;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
WMAtom: TAtom;
ActualTypeReturn: TAtom;
ActualFormatReturn: LongInt;
NItemsReturn, BytesAfterReturn: Cardinal;
Ptr: PByte;
screen: PGdkScreen;
Valid: Boolean;
begin
screen:=gdk_screen_get_default;
Display := gdk_x11_get_default_xdisplay;
if Display = nil then
exit;
ScreenNum := gdk_screen_get_number(screen);
RootWin := gdk_x11_get_default_root_xwindow;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
Valid:=XGetWindowProperty(Display, RootWin, WMAtom, 0, 1, False,
AnyPropertyType, @ActualTypeReturn,
@ActualFormatReturn, @NItemsReturn,
@BytesAfterReturn, @Ptr)=0;
if Valid then
try
if (ActualTypeReturn = None) or (ActualFormatReturn <> 32) or not Assigned(Ptr) then
Valid := False;
if Valid then Result := PCardinal(Ptr)^;
finally
if Assigned(Ptr) then
XFree(Ptr);
end;
end;
{$ENDIF}
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
procedure TGtk2WidgetSet.BringFormToFront(Sender: TObject); procedure TGtk2WidgetSet.BringFormToFront(Sender: TObject);
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}

View File

@ -3719,6 +3719,14 @@ begin
then g_list_free(TopList); then g_list_free(TopList);
end; end;
function TGtk2WidgetSet.GetForegroundWindow: HWND;
begin
Result:=0;
{$IFDEF HASX}
Result:=X11GetActiveWindow;
{$ENDIF}
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
Function: GetDIBits Function: GetDIBits
Params: Params:
@ -8114,6 +8122,7 @@ var
GdkWindow: PGdkWindow; GdkWindow: PGdkWindow;
AForm: TCustomForm; AForm: TCustomForm;
begin begin
try
{$IFDEF VerboseFocus} {$IFDEF VerboseFocus}
DbgOut('TGtk2WidgetSet.SetForegroundWindow hWnd=',DbgS(hWnd)); DbgOut('TGtk2WidgetSet.SetForegroundWindow hWnd=',DbgS(hWnd));
LCLObject:=TControl(GetLCLObject(Pointer(hWnd))); LCLObject:=TControl(GetLCLObject(Pointer(hWnd)));
@ -8152,6 +8161,7 @@ begin
{$ENDIF} {$ENDIF}
gdk_window_show(GdkWindow); gdk_window_show(GdkWindow);
gdk_window_raise(GdkWindow); gdk_window_raise(GdkWindow);
gdk_window_focus(GdkWindow, gtk_get_current_event_time);
{$IFDEF DebugGDKTraps} {$IFDEF DebugGDKTraps}
EndGDKErrorTrap; EndGDKErrorTrap;
{$ENDIF} {$ENDIF}
@ -8159,6 +8169,11 @@ begin
gtk_window_present(PGtkWindow(hWnd)); gtk_window_present(PGtkWindow(hWnd));
end; end;
end; end;
except
{$IFDEF HASX}
Result:=X11Raise(hWnd);
{$ENDIF}
end;
end; end;
function TGtk2WidgetSet.SetMapMode(DC: HDC; fnMapMode : Integer): Integer; function TGtk2WidgetSet.SetMapMode(DC: HDC; fnMapMode : Integer): Integer;

View File

@ -124,6 +124,7 @@ function GetDeviceSize(DC: HDC; var p: TPoint): boolean; override;
function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; override; function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; override;
function GetFocus: HWND; override; function GetFocus: HWND; override;
function GetFontLanguageInfo(DC: HDC): DWord; override; function GetFontLanguageInfo(DC: HDC): DWord; override;
function GetForegroundWindow: HWND; override;
function GetKeyState(nVirtKey: Integer): Smallint; override; function GetKeyState(nVirtKey: Integer): Smallint; override;
function GetMapMode(DC: HDC): Integer; override; function GetMapMode(DC: HDC): Integer; override;
function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override; function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override;

View File

@ -203,6 +203,8 @@ type
function QtVersionCheck(const AMajor, AMinor, AMicro: Integer): Boolean; function QtVersionCheck(const AMajor, AMinor, AMicro: Integer): Boolean;
{$IFDEF HASX11} {$IFDEF HASX11}
function IsCurrentDesktop(AWidget: QWidgetH): Boolean; function IsCurrentDesktop(AWidget: QWidgetH): Boolean;
function X11Raise(AHandle: HWND): boolean;
function X11GetActiveWindow: HWND;
function GetWindowManager: String; function GetWindowManager: String;
procedure SetSkipX11Taskbar(Widget: QWidgetH; const ASkipTaskBar: Boolean); procedure SetSkipX11Taskbar(Widget: QWidgetH; const ASkipTaskBar: Boolean);
{check if we are running under kde3 installation} {check if we are running under kde3 installation}

View File

@ -4958,11 +4958,8 @@ begin
else else
inherited Activate; inherited Activate;
{$IFDEF HASX11} {$IFDEF HASX11}
// qt X11 bug ? activates window but it's not in
// front of others.
{$note TQtWidget.Activate: Check this with next qt version (>=4.7)}
if not QWidget_isModal(Widget) then if not QWidget_isModal(Widget) then
QWidget_raise(Widget); X11Raise(QWidget_winId(Widget));
{$ENDIF} {$ENDIF}
end; end;

View File

@ -4972,13 +4972,27 @@ begin
end; end;
end; end;
function TQtWidgetSet.GetForegroundWindow: HWND;
begin
Result:=0;
{$IFDEF HASX11}
Result:=X11GetActivewindow;
{$ENDIF}
end;
function TQtWidgetSet.SetForegroundWindow(HWnd: HWND): boolean; function TQtWidgetSet.SetForegroundWindow(HWnd: HWND): boolean;
begin begin
Result := False; Result := False;
if HWND <> 0 then if HWND <> 0 then
begin begin
try
Result := TQtWidget(HWND).IsActiveWindow; Result := TQtWidget(HWND).IsActiveWindow;
TQtWidget(HWnd).Activate; TQtWidget(HWnd).Activate;
except
{$IFDEF HASX11}
Result:=X11Raise(HWnd);
{$ENDIF}
end;
end; end;
end; end;

View File

@ -111,6 +111,7 @@ function GetDeviceSize(DC: HDC; var P: TPoint): Boolean; Override;
function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; Override; function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; Override;
function GetDoubleClickTime: UINT; override; function GetDoubleClickTime: UINT; override;
function GetFocus: HWND; override; function GetFocus: HWND; override;
function GetForegroundWindow: HWND; override;
function GetKeyState(nVirtKey: Integer): Smallint; override; function GetKeyState(nVirtKey: Integer): Smallint; override;
function GetMapMode(DC: HDC): Integer; override; function GetMapMode(DC: HDC): Integer; override;
function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override; function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override;

View File

@ -81,6 +81,69 @@ begin
end; end;
end; end;
function X11Raise(AHandle: HWND): boolean;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
XClient: TXClientMessageEvent;
WMAtom: TAtom;
begin
Result:=false;
Display := QX11Info_display();
if Display = nil then
exit;
ScreenNum := QX11Info_appScreen();
RootWin := XRootWindow(Display, ScreenNum);
XClient._type := ClientMessage;
XClient.window := AHandle;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
XClient.message_type := WMATom;
XClient.format := 32;
XClient.data.l[0] := 1;
XClient.data.l[1] := 0;
XClient.data.l[2] := 0;
Result:=XSendEvent (Display, RootWin, False,
SubstructureRedirectMask or SubstructureNotifyMask,
@XClient)<>0;
end;
function X11GetActivewindow: HWND;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
WMAtom: TAtom;
ActualTypeReturn: TAtom;
ActualFormatReturn: LongInt;
NItemsReturn, BytesAfterReturn: Cardinal;
Ptr: PByte;
Valid: Boolean;
begin
Display := QX11Info_display();
if Display = nil then
exit;
ScreenNum := QX11Info_appScreen();
RootWin := XRootWindow(Display, ScreenNum);
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
Valid:=XGetWindowProperty(Display, RootWin, WMAtom, 0, 1, False,
AnyPropertyType, @ActualTypeReturn,
@ActualFormatReturn, @NItemsReturn,
@BytesAfterReturn, @Ptr)=0;
if Valid then
try
if (ActualTypeReturn = None) or (ActualFormatReturn <> 32) or not Assigned(Ptr) then
Valid := False;
if Valid then Result := PCardinal(Ptr)^;
finally
if Assigned(Ptr) then
XFree(Ptr);
end;
end;
function GetWindowManager: String; function GetWindowManager: String;
{used to get window manager name, so we can handle different wm's behaviour {used to get window manager name, so we can handle different wm's behaviour
eg. kde vs. gnome} eg. kde vs. gnome}